区间列表的交集

205 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

题目描述

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

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

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

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

示例 1:

输入:firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]] 输出:[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

示例 2:

输入:firstList = [[1,3],[5,9]], secondList = [] 输出:[]

示例 3:

输入:firstList = [], secondList = [[4,8],[10,12]] 输出:[]

示例 4:

输入:firstList = [[1,7]], secondList = [[3,10]] 输出:[[3,7]]

提示:

  • 0 <= firstList.length, secondList.length <= 1000
  • firstList.length + secondList.length >= 1
  • 0 <= starti < endi <= 109
  • endi < starti+1
  • 0 <= startj < endj <= 109
  • endj < startj+1

思路

方法一:暴力解法

两重for循环遍历每一个集合,把两集合的公共区间加入我们的答案数组中,这里唯一的难点就是判断有无交集,这里判断的方法是:用两集合右端点的最小值减去左端点的最大值之间的差和0比较,如果大于等于,说明两个集合有公共区间。

image.png

注意:这里可以进行优化:如果i集合的右端点,小于j集合的左端点,说明两集合没有交集,且j后面的集合也没有,可以提前结束小循环

方法二:双指针

两个指针扫描两个数组,如果两个数组有交集(判断方式同暴力解法相同),就把交集加入到答案数组中,这里要注意的时指针移动的条件,两区间求交集后,小区间不会和后面的区间有交集了,但是大区间可能还会有,所以这里每一次循环都要移动小指针的位置。

代码

解法一:

class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
​
        int length1 = firstList.size(), length2 = secondList.size();
        vector<vector<int>> res;
        int j = 0;
        for(int i = 0;i < length1;i ++)
        {   
            vector<int> t1 = firstList[i];             
            for(int j = 0;j < length2;j ++)
            {
                vector<int> t2 = secondList[j];
                // 优化:当第一个区间最大的数小于第二个区间最小的数时,后面的的区间都不用在判断了
                if(t1[1] < t2[0]) break;
                // 判断有无交集
                int qt = min(t1[1], t2[1]) - max(t1[0], t2[0]);
                if( qt >= 0)
                {
                    vector<int> ans;
                    ans.push_back(max(t1[0], t2[0]));
                    ans.push_back(min(t1[1], t2[1]));
                    res.push_back(ans);
                }  
            }
        }
        return res;
    }
};

解法二:

class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& firstList, vector<vector<int>>& secondList) {
​
        int length1 = firstList.size(), length2 = secondList.size();
        vector<vector<int>> res;
​
        int i = 0, j = 0;
        while(i < length1 && j < length2)
        {
            auto t1 = firstList[i];
            auto t2 = secondList[j];
            int start = max(t1[0], t2[0]);
            int end = min(t1[1], t2[1]);
            
            if(end >= start)
            {
                vector<int> ans;
                ans.push_back(start);
                ans.push_back(end);
                res.push_back(ans);
            } 
​
            if(firstList[i][1] < secondList[j][1]) i++;
            else j++;
​
        }
​
​
        return res;
    }
};