题目描述
给定一个区间的集合 ,其中 。返回 需要移除区间的最小数量,使剩余区间互不重叠 。
用例
输入:
输出:
解释: 移除 后,剩下的区间没有重叠。
输入:
输出:
解释: 你需要移除两个 来使剩下的区间没有重叠。
输入:
输出:
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
题目分析
这就是经典的活动选择类问题,活动选择问题是给定一堆活动,让你进行选择,约束是一个活动结束了才能参加下一个活动(即下一个活动开始时间不小于上一个活动结束时间),问最多参与多少个活动。要想尽可能多参加活动,直观的策略是参加活动时长短的活动,但是这个贪心策略容易找到反例,即活动时长短的活动可能卡住两个不重合的长活动。理想贪心策略是优先参加活动结束时间早的活动。
简单用数学归纳法说明贪心策略的正确性。
我们对算法的步骤进行归纳证明。
归纳基础,你用结束时间最早的活动替换最优解的第一个活动,得到的解显然仍然是最优解,即存在包括最早结束时间的活动的最优活动安排。
归纳假设,存在最优活动安排包含算法第步得到的活动。
归纳步骤,存在最优活动安排,其中是按算法 to 步所得。首先,我们用算法第步得到的活动替换并没有破坏活动之间的约束,同时,经过替换后得到的活动序列的长度并没有变少,故而它也是最优活动安排。
回到无重叠区间问题,那么解法就简单了。第一步,我们对各个区间按区间后边界进行升序排序;第二步,我们按照贪心策略遍历各个区间,如果该区间前边界小于上一选定的区间后边界,则删除数累加,否则更新上一选定区间;最后,返回累加数。
代码
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
int del_num= 0;
// sort
sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b){
return a[1]< b[1];
});
// count
for(int i= 1, k= 0; i< intervals.size(); i++){
if(intervals[i][0]< intervals[k][1]){del_num+= 1;}
else{k= i;}
}
return del_num;
}
};
其中,时间复杂度.