• # 区间合并总结


    区间合并总结

    区间合并总体来说还是比较简单的,通过模拟基本都能做出来,不过要注意下标越界的情况。

    例题:

    1.合并区间(https://leetcode-cn.com/problems/merge-intervals/)

    以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

    思路:将区间按左端点从小到大排成序列,然后通过对相邻区间的"右左"端点判断是否有交集,然后通过模拟完成区间合并。

    class Solution {
    public:
        
        vector<vector<int>> merge(vector<vector<int>>& intervals) {
            vector<vector<int>> ans;
            sort(intervals.begin(),intervals.end());
            int tmp = 0;
            for(int i=0;i<intervals.size();i++){
                int L = intervals[i][0] , R = intervals[i][1];
                if(!ans.size() || ans.back()[1]<L){ //若已放区间中右端点最大值都小于该区间的最小值,则将该区间放入
                    ans.push_back({L,R});
                }
                else {
                    ans.back()[1]=max(ans.back()[1],R); //更新右端点
                }
            }
            return ans;
        }
    };
    
    

    2.插入区间(https://leetcode-cn.com/problems/insert-interval/)

    给你一个 无重叠的 ,按照区间起始端点排序的区间列表。

    在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。

    思路:详见代码

    class Solution {
    public:
        vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
            vector<vector<int>>ans;
            int left = newInterval[0];
            int right = newInterval[1];
            bool flag=0;
            for(auto &interval : intervals){
                if(interval[0]>right){ //在插入区间右侧
                    if(!flag){
                        ans.push_back({left,right});
                        flag=1;
                    }
                    ans.push_back(interval);
                }
                else if(interval[1]<left){ //在插入区间左侧
                    ans.push_back(interval);
                }
                else {//更新左右端点
                    left = min(left,interval[0]);
                    right = max(right,interval[1]);
                }
            }
            if(!flag) ans.push_back({left,right});
            return ans;
        }
    };
    

    3.无重叠区间(https://leetcode-cn.com/problems/non-overlapping-intervals/)

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

    注意:

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

    思路:详见代码

    class Solution {
    public:
        int eraseOverlapIntervals(vector<vector<int>>& intervals) {
            sort(intervals.begin(),intervals.end());
            int n = intervals.size();
            if(n == 0) return 0;
            vector<int>st(n,0); //标记删除区间
            int ans = 0;
            int L = intervals[0][0],R = intervals[0][1]; //标记被比较的区间
            int pos = 0;
            for(int i=1;i<n;i++){
                if(!st[pos] && !st[i] && intervals[i][0] < R){ 
                    if(intervals[i][1] >= R) //删除右端点大的那个区间
                        st[i] = 1;
                    else {
                        st[pos] = 1; 
                        L = intervals[i][0]; //更新被比较的区间
                        R = intervals[i][1];
                        pos = i;
                    }
                    ans++;
                }
                else {
                    L = intervals[i][0];//更新被比较的区间
                    R = intervals[i][1];
                    pos = i;
                }
            }
            return ans;
        }
    };
    

    4.区间列表的交集(https://leetcode-cn.com/problems/interval-list-intersections/)

    给定两个由一些 闭区间 组成的列表,firstList 和 secondList ,其中 firstList[i] = [starti, endi] 而 secondList[j] = [startj, endj] 。每个区间列表都是成对 不相交 的,并且 已经排序 。

    返回这 两个区间列表的交集 。

    形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a <= x <= b 。

    两个闭区间的 交集 是一组实数,要么为空集,要么为闭区间。例如,[1, 3] 和 [2, 4] 的交集为 [2, 3] 。

    思路:双指针,分别指向两个列表,两个区间不相交时,谁的区间小,移动谁的指针,相交时,则放入列表。注意指针越界。

    class Solution {
    public:
        vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
            vector<vector<int>> ans;
            int l = 0,r = 0;
            while(l<firstList.size() && r<secondList.size()){
                while(l < firstList.size() && r < secondList.size()){
                    if(l >= firstList.size() || r >= secondList.size()) break; //防止越界
                    if(firstList[l][1] < secondList[r][0]) l++; //first区间在second区间左边
                    else if(firstList[l][0] > secondList[r][1]) r++; //first区间在second区间右边
                    else break;//说明此时有交集或某一区间已经遍历完
                }
                if(l >= firstList.size() || r >= secondList.size()) break;//防越界
                int lmin = firstList[l][0],lmax = firstList[l][1];
                int rmin = secondList[r][0],rmax = secondList[r][1];
                // cout<<l<<' '<<r<<endl;
                ans.push_back({max(lmin,rmin),min(lmax,rmax)});
                //右区间小的++
                if(l < firstList.size() && secondList[r][1] > firstList[l][1]) l++; 
                else if(r < secondList.size() && secondList[r][1] <= firstList[l][1])r++;
            }
            return ans;
        }
    };
    
    七月在野,八月在宇,九月在户,十月蟋蟀入我床下
  • 相关阅读:
    libiconv2.dll
    windows下安装,配置gcc编译器
    STM32之DMA
    keilkill.bat
    STM32之系统滴答定时器
    STM32库函数开发使用总结
    STM32之串口通信
    yocto系统介绍
    fork子进程僵尸问题及解决方案
    shell实现的守护进程
  • 原文地址:https://www.cnblogs.com/voids5/p/14366547.html
Copyright © 2020-2023  润新知