浏览器标题切换
浏览器标题切换end

区间问题(非DP类型)及变形

解题思路

  1. 画图 -> 转换成线段问题
  2. 排序:起点(左)升序排序,起点一样按照终点(右)降序排序。
  3. 分三种情况讨论:覆盖、相交、无交集

注意参数写法

二维vector自定义排序(c++ lambda写法)

        // 二维vector排序:起点(左)升序排序,起点一样按照终点(右)降序排序
        sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b) {
            if (a[0]!= b[0]) return a[0]<b[0]; // 起点升序
            return a[1]>b[1]; // 终点降序
        });

模版 - Leetcode1288.删除被覆盖区间

class Solution {
public:
    int removeCoveredIntervals(vector<vector<int>>& intervals) {

        // 二维vector排序:起点(左)升序排序,起点一样按照终点(右)降序排序
        sort(intervals.begin(), intervals.end(), [](vector<int>& a, vector<int>& b) {
            if (a[0]!= b[0]) return a[0]<b[0]; // 起点升序
            return a[1]>b[1]; // 终点降序
        });

        int l=intervals[0][0];
        int r=intervals[0][1];
        int ans=0; 

        // 分三种情况讨论
        for(int i=1;i<intervals.size();i++)
        {
            int a=intervals[i][0];
            int b=intervals[i][1];

            // 情况1:某一个区间完全覆盖了另一个区间(不需要更新边界,上面的范围比下一个大,因为终点降序排的)
            if(a>=l && b<=r)
                ans++;

            // 情况2:部分相交 -> 合并成一个更大的区间 (保留起点,更新终点)
            if(a<=r && b>=r)// if(a>=l && b>r)
                r=b;

            // 情况3:完全不相交 -> 更新起点和终点
            if(a>r)
                l=a,r=b;
        }

        return intervals.size()-ans;
    }
};

变形题

  • 228. 汇总区间: 贪心/暴力+特判

  • 56.合并区间

  • 57.插入区间:转换成区间合并问题 -> 输出合并后的每个最大区间

  • 986.区间列表的交集

    • 首先说明,该题官方题解里面做好的解法是双指针,但是线段区间的判断方法可以AC,但是速度不是最快,但是比较好想到这个思路。(first和second数组合并后求相交区间,记得特判覆盖的情况,存在覆盖则保留覆盖面小的那个数组然后continue)
  • 452. 用最少数量的箭引爆气球:(正确思路 - 贪心维护右端点)
    转换成求区间相交个数,然后判断香蕉个数奇偶性,因为一个箭可以射两个气球(也就是交点个数)。所以交点个数的奇偶性决定了箭的个数。记得特判交点为0的情况(直接输出区间/气球个数)即可。(这个思路有问题)

    • 特殊例子:[1,2],[4,5],[1,5] 应该输出2 (按照上面思路 答案会输出1 答案错误)
    • 正确思路:不能去求区间相交个数,直接用贪心思想,维护线段右端点,按照右端点从小到达排序,不需要管左端点。若i-1的右端点和i的左端点不相交,则ans+1,更新当前右端点为i的右端点。

参考

戳这里-微信公众号

posted @ 2024-03-17 06:09  抓水母的派大星  阅读(2)  评论(0编辑  收藏  举报