leetcode——第435题——区间问题—无重复区间

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

注意:

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

class Solution {
/*
排序过程:

按照右边界排序,就要从左向右遍历,因为右边界越小越好,只要右边界越小,留给下一个区间的空间就越大,所以从左向右遍历,优先选右边界小的。

按照左边界排序,就要从右向左遍历,因为左边界数值越大越好(越靠右),这样就给前一个区间的空间就越大,所以可以从右向左遍历。

如果按照左边界排序,还从左向右遍历的话,要处理各个区间右边界的各种情况。
*/

// 这题有两个出彩的地方:
// 1、排序是个亮点
// 2、没有直接去求移除区间的个数,而是转换一下思路,先去求非交叉区间的个数
//    用总个数 减去 非交叉区间个数 ,最终求得需要移除的区间个数

// // ***************************方法一:从左向右遍历按照右边界排序
// private:
//     static bool cmp(const vector<int>& a, const vector<int>& b)
//     {
//         // 右边界排序,从左向右遍历

//         // 这里对于 a[0] 与 b[0] 的比较 升序、降序 都对,因为后面的处理主要就是看右边界
//         // 左边界怎么样都是 可以的!!!!
//         // if(a[1] == b[1])
//         // {
//         //     return a[0] < b[0];
//         // }
//         return a[1] < b[1];
//     }

// public:
    // int eraseOverlapIntervals(vector<vector<int>>& intervals) 
    // {
    //     if(intervals.size() == 0)   return 0;
    //     sort(intervals.begin(), intervals.end(), cmp);

    //     int result = 1;
    //     int end = intervals[0][1]; //将按照右边界排序后第一个元素的右下标赋值给end
    //     for(int i = 1; i < intervals.size(); i++)
    //     {
    //         if(end <= intervals[i][0])
    //         {
    //             result++;
    //             end = intervals[i][1];
    //         }
    //     }
    //     // 注意上面获得是无重复区间个数,这里不要忘记用总数做减法哦~~
    //     return intervals.size() - result;
    // }

// ***************************方法二:与引爆气球的思路类似
private:
    static bool cmp(const vector<int>& a, const vector<int>& b)
    {
        // 在本方法中,cmp 函数定义为 对左边界排升序或者是 对右边界排升序 都是对滴!
        // return a[1] < b[1];
        return a[0] < b[0];
    }

public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) 
    {
        if(intervals.size() == 0)   return 0;
        sort(intervals.begin(), intervals.end(), cmp);

        int result = 1; // 记录无重复区间个数

        // 第一种 for 循环
        for(int i = 1; i < intervals.size(); i++)
        {
            // 当前第 i 个元素的左边界 月 前一个元素的右边界比较
            if(intervals[i][0] < intervals[i - 1][1])
            {
                // 如果被包含在了前一个元素的右边界,则更新当前元素的右边界,取最小值
                intervals[i][1] = min(intervals[i][1], intervals[i - 1][1]);
            }
            // 如果没有包含,说明是无重复的两个区间,则将无重复区间个数 +1
            else
            {
                result++;
            }
        }

        // // 第二种for循环,两种写法都是对的
        // int start = intervals[0][0];
        // int end = intervals[0][1];
        // for(int i = 1; i < intervals.size(); i++)
        // {
        //     if(intervals[i][0] < end)
        //     {
        //         // 更新start 为最大,end 为最小,尽可能缩小范围  
        //         start = max(intervals[i][0], start);
        //         end = min(intervals[i][1], end);
        //     }
        //     else
        //     {
        //         result++;
        //         // 重新个 start 和 end 赋值          
        //         start = intervals[i][0];
        //         end = intervals[i][1];
        //     }
        // }
        return intervals.size() - result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值