zoukankan      html  css  js  c++  java
  • [刷题] 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

    应用

    • 最小生成树
    • 最短路径
  • 相关阅读:
    堆栈学习
    需要阅读的书籍
    Rust Book Lang Ch.19 Fully Qualified Syntax, Supertraits, Newtype Pattern, type aliases, never type, dynamic sized type
    Rust Lang Book Ch.19 Placeholder type, Default generic type parameter, operator overloading
    Rust Lang Book Ch.19 Unsafe
    Rust Lang Book Ch.18 Patterns and Matching
    Rust Lang Book Ch.17 OOP
    Rust Lang Book Ch.16 Concurrency
    Rust Lang Book Ch.15 Smart Pointers
    HDU3966-Aragorn's Story-树链剖分-点权
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12776773.html
Copyright © 2011-2022 走看看