# 区间合并总结

区间合并总结

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

例题:

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;
    }
};
七月在野,八月在宇,九月在户,十月蟋蟀入我床下
原文地址:https://www.cnblogs.com/voids5/p/14366547.html