leetcode435:无重叠区间

leetcode435:无重叠区间

本题为选择不相交区间问题,是一个经典的贪心算法问题

《算法入门经典》中有对选择不相交问题的求解思路的描述:
问题描述:数轴上有n个开区间,选择尽量多的区间,使得这些区间两两之间没有公共交点。
分析:
(1)首先明确一个问题,假设有两个区间想想x,y,区间x完全包含y。那么,选x是不划算的,因为x,和y之间最多只能选一个,选x还不如选y,这样不仅区间数目不会减少,而且给其他区间留出了更多的位置。接下来,按照bi从小到大的顺序给区间排序。贪心策略,是一定要选第一个区间。
至于为什么,简要的分析一下;
现在已经排好序了,并b1<=b2<=b3<=…,考虑a1和a2的大小关系;
1.a1>a2,那么区间2就包含a1了,所以a2肯定不选,选a1;并却推广,以后的区间如果存在i 有ai<a1,i区间不要,只要1;
2.排除了1这种情况,一定有a1<=a2<=a3<=a4…那么如果区间a2和区间a1完全不相交,那么对策略没影响,区间1和2都要。否则区间1和区间2只能选一个,我们贪心只选择前一个。

一、题目

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠

示例 1:

输入: [ [1,2], [2,3], [3,4], [1,3] ]

输出: 1

解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:

输入: [ [1,2], [1,2], [1,2] ]

输出: 2

解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:

输入: [ [1,2], [2,3] ]

输出: 0

解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

二、求解

1.贪心思想:找到需要移除的区间的最小数目,其实就是选择不相交区间,使不相交区间的数目最大。而选择不相交区间,应该使每一次选择的区间都对后面的选择影响最小,如果从前往后选择,那么选择区间右端点靠前的区间,从后往前则选择区间左端点靠后的区间。
2.步骤:采用从前往后选择

  1. 对所有的区间,按照区间右端点从小到大排序。

代码如下:

int n=intervals.size();
         sort(intervals.begin(),intervals.end(),[](vector<int>& a,vector<int>& b){return a[1]<b[1];});

2.每次都选择区间右端点最小的区间,由于已经对区间右端点排好序了,只需要从前往后遍历即可,要注意不相交=下一个区间的左端点在上一个区间的右端点后面,因此引入index记录上一个区间的右端点。

代码如下:

     int index=intervals[0][0];//引入一个标记记录当前选择区间的最右值
         int ans=0;
        for(int i=0;i<n;i++)
        {       
            if(intervals[i][0]>=index)
            {
                index=intervals[i][1];
                ans++;
            }
        }

3.完整代码

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
         int n=intervals.size();
         sort(intervals.begin(),intervals.end(),[](vector<int>& a,vector<int>& b){return a[1]<b[1];});//预处理按区间右端点从小到大排列
         int index=intervals[0][0];//引入一个标记记录当前选择区间的最右值
         int ans=0;
        for(int i=0;i<n;i++)
        {       
            if(intervals[i][0]>=index)
            {
                index=intervals[i][1];
                ans++;
            }
        }
        return n-ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值