貪心演算法之區間排程問題
阿新 • • 發佈:2020-11-22
前言
435. 無重複區間
-
經典的貪心演算法問題
Interval Scheduling
(區間排程問題)。給你很多形如[start, end]
的閉區間,請你設計一個演算法,算出這些區間中最多有幾個互不相交的區間。 -
本題的主要思路在於貪心性質,對於所給多個閉區間,怎麼才能求出互不相交的區間呢?
-
如:
[1,3]和[3,4]
或者[1,3]和[4,7]和[8,9]
都是不相交的。這裡的[1,3]和[3,4]
也屬於不相交的範圍。
- 可以先對原陣列
按end大小升序排序
,接著定義一個x_end
為最小的end,之後再尋找start>x_end
public int intervalSchedule(int[][] intervals){ //至少有一個區間不重複 int count = 1; //按每個區間的end升序 Arrays.sort(intervals, new Comparator<int[]>(){ public int compare(int[] a, int[] b){ //由於a[1] - b[1]有溢位可能,所以用比較的方式 return a[1] < b[1] ? -1 : 1; } }); //已經升序,故第一個end為最小值 int x_end = intervals[0][1]; //每次start >= x_end就多一個區間,並且x_end為此時end for(int[] interval : intervals){ int start = interval[0]; if(start >= x_end){ count++; x_end = interval[1]; } } return count; }
-
計算出移除區間後使得剩下的都是無重複區間,不就是先把那些無重複區間計算出來,然後用區間長度去減麼?
-
那麼此時只需要return n - intervalSchedule(intervals);
int eraseOverlapIntervals(int[][] intervals) {
int n = intervals.length;
return n - intervalSchedule(intervals);
}
452.用最少數量的箭引爆氣球
-
本題參考435的區間排程問題,容易發現兩者的輸入很相似,但是有一點,當兩個氣球的區間邊緣接觸時,是可以一隻箭引爆這兩個氣球的,所以
intervalSchedule
if(start > x_end)
-
這裡可以理解為,本來
intervalSchedule
返回的count是無重複區間,那麼至少需要count只箭,由於區間邊緣相等時可以用一隻箭同時引爆兩個氣球,所以此時不必count++。