• [刷题] 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

    应用

    • 最小生成树
    • 最短路径
  • 相关阅读:
    02月23日总结
    02月24日总结
    02月27日总结
    02月28日总结
    网络编程:UDP网路编程
    网络编程:本地套接字
    网络编程:TIME_WAITE
    网络编程:TCP 网络编程
    RPC实战与核心原理之如何在没有接口的情况下进行RPC调用
    大三寒假学习 spark学习 spark安装
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12776773.html
Copyright © 2020-2023  润新知