[刷题] 435 Non-overlapping Intervals

要求

  • 贪心算法与动态规划的关系
  • 给定一组区间,最少删除多少个区间,可以让这些区间之间互相不重叠
  • 给定区间的起始点永远小于终止点

示例

  • [[1,2],[2,3],[3,4],[1,3]], 返回1
  • [[1,2],[1,2],[1,2]], 返回2

思路

  • 等价为最多保留多少个区间
  • 暴力:找出所有子区间的组合,判断不重叠((2^n)*n)
  • 先排序,方便判断不重叠
  • 具体实现类似最长上升子序列
  • 选择区间的结尾很重要,结尾越小,留给后面的空间越大

实现

  • 动态规划(n^2)
  • dp[i]:使用intervals[0...i]的区间所能构成的最长不重叠区间序列
 1 class Solution {
 2 public:
 3     int eraseOverlapIntervals(vector<vector<int>>& intervals) {
 4 
 5         if(intervals.size() == 0)
 6             return 0;
 7 
 8         sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){
 9             if(a[0] != b[0]) return a[0] < b[0];
10             return a[1] < b[1];
11         });
12 
13         vector<int> dp(intervals.size(), 1);
14         for(int i = 1 ; i < intervals.size() ; i ++)
15             for(int j = 0 ; j < i ; j ++)
16                 if(intervals[i][0] >= intervals[j][1])
17                     dp[i] = max(dp[i], 1 + dp[j]);
18 
19         return intervals.size() - dp.back();
20     }
21 };
View Code
  • 贪心算法(n)
  • 按照区间结尾排序,每次选择结尾最早的,且和前一个区间不重叠的区间
  • 贪心选择性质:贪心算法为A,最优算法为O,A完全能替代O,且不影响求出最优解
  • 若无法使用贪心算法,举出反例即可
  • 证明正确性,可使用数学归纳法
    • 某次选择的是[s(i),f(i)],其中f(i)是当前所有选择中结尾最早的
    • 假设这个选择不是最优的,若最优解为k,则这个选择得到的解,最多为k-1
    • 假设最优解在这一步选择[s(j),f(j)],其中f(j)>f(i)
    • 显然可用[s(i),f(i)]替换[s(j),f(j)],而不影响后续的区间选择
    • 即当选择[s(i),f(i)]时,也构成了大小为k的解,矛盾
    • 此问题具有贪心选择性,可以用贪心算法得到最优解
 1 class Solution {
 2 
 3 public:
 4     int eraseOverlapIntervals(vector<vector<int>>& intervals){
 5 
 6         if(intervals.size() == 0)
 7             return 0;
 8 
 9         sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){
10             if(a[0] != b[0]) return a[0] < b[0];
11             return a[1] < b[1];
12         });
13 
14         int res = 1;
15         int pre = 0;
16         for(int i = 1 ; i < intervals.size() ; i ++)
17             if(intervals[i][0] >= intervals[pre][1]){
18                 pre = i;
19                 res ++;
20             }
21             else if(intervals[i][1] < intervals[pre][1])
22                 pre = i;
23 
24         return intervals.size() - res;
25     }
26 };
View Code

应用

  • 最小生成树
  • 最短路径
原文地址:https://www.cnblogs.com/cxc1357/p/12776773.html