贪心算法之区间调度问题
前言
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
的区间,如果有则count++,然后更新x_end=此时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
需要修改start >= 为 >。if(start > x_end)
-
这里可以理解为,本来
intervalSchedule
返回的count是无重复区间的个数,那么至少需要count只箭,由于区间边缘相等时可以用一只箭同时引爆两个气球,所以此时不必count++。