LeetCode 435 区间无重叠问题(Medium)
题目描述
给定一个区间的集合
intervals
,其中intervals[i] = [starti, endi]
返回 需要移除区间的最小数量,使剩余区间互不重叠
示例 1:
输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。
- 示例 2:
输入: intervals = [ [1,2], [1,2], [1,2] ] 输出: 2 解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
题目解析
贪心(如何选首区间\尾区间)
本题其实与预定会议十分相似,现需排若干个会议,但只有一个会议室可以使用,如何安排能够使会议数最大。
对于会议安排,通常都会选择最早结束的会议先排,这样其他会议才有更多的选择
同理,把区间看成会议的起止时间,我们也能够通过排序找出右端点最小的区间,将其排在首位
之后,若下一区间的左端点不小于上一个保留区间的右端点,则将其保留,否则舍弃
此外,会议安排还可以先安排最晚开始的会议,依次先前递推
将区间按左端点排序,将左端点最大的区间选作最后一个区间
之后,若前一个区间的右端点不大于其后的保留区间左端点,则将其保留,否则舍弃
但是,不可以先排最早开始的会议,原因很简单,不知道会议何时结束,同理,也不可以先排最晚结束的会议
- 动态规划(优化参考leetcode 300 此处重点说明为什么前面的算法是贪心)
- 对于每一个区间,都可以考虑让其作为最后的区间,来看此时它前面的区间是否与它重叠
- 若重叠,则不能作为最后的区间,若不重叠,则可以
- 可知每个区间作为最后区间时,区间总数为当其前一个区间作为最后区间时,区间总数 + 1 或 与其相等
- 由此可进行动态规划,让每个区间都进行尝试,而不是贪心的认为,左端点最小的区间就是尾区间
代码示例
class Solution { public: int eraseOverlapIntervals(vector<vector<int>>& intervals) { if(intervals.size() == 0 || intervals.size() == 1) return 0; //这里使用了lambda表达式 sort(intervals.begin(),intervals.end(),[](vector<int> a, vector<int> b) ->bool {return a[0] < b[0];}); int tmp = 0; int prev = intervals[intervals.size() - 1][0]; for(int i = intervals.size() - 1 ; i > 0 ; i--) { if(intervals[i-1][1] > prev) tmp++; else prev = intervals[i-1][0]; } return tmp; } };