双指针题目:区间列表的交集

题目

标题和出处

标题:区间列表的交集

出处:986. 区间列表的交集

难度

4 级

题目描述

要求

给定两个由闭区间组成的列表, firstList \texttt{firstList} firstList secondList \texttt{secondList} secondList,其中 firstList[i]   =   [start i ,   end i ] \texttt{firstList[i] = [start}_\texttt{i}\texttt{, end}_\texttt{i}\texttt{]} firstList[i] = [starti, endi] secondList[j]   =   [start j ,   end j ] \texttt{secondList[j] = [start}_\texttt{j}\texttt{, end}_\texttt{j}\texttt{]} secondList[j] = [startj, endj]。同一个区间列表中的区间各不相交,并且已经排序

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

闭区间 [a,   b] \texttt{[a, b]} [a, b](其中 a ≤ b \texttt{a} \le \texttt{b} ab)表示满足 a ≤ x ≤ b \texttt{a} \le \texttt{x} \le \texttt{b} axb 的实数 x \texttt{x} x 的集合。

两个闭区间的交集是一组实数,为空集或闭区间。例如, [1,   3] \texttt{[1, 3]} [1, 3] [2,   4] \texttt{[2, 4]} [2, 4] 的交集为 [2,   3] \texttt{[2, 3]} [2, 3]

示例

示例 1:

示例 1

输入: firstList   =   [[0,2],[5,10],[13,23],[24,25]],   secondList   =   [[1,5],[8,12],[15,24],[25,26]] \texttt{firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]} 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]] \texttt{[[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]} [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

示例 2:

输入: firstList   =   [[1,3],[5,9]],   secondList   =   [] \texttt{firstList = [[1,3],[5,9]], secondList = []} firstList = [[1,3],[5,9]], secondList = []
输出: [] \texttt{[]} []

数据范围

  • 0 ≤ firstList.length,   secondList.length ≤ 1000 \texttt{0} \le \texttt{firstList.length, secondList.length} \le \texttt{1000} 0firstList.length, secondList.length1000
  • firstList.length + secondList.length ≥ 1 \texttt{firstList.length} + \texttt{secondList.length} \ge \texttt{1} firstList.length+secondList.length1
  • 0 ≤ start i < end i ≤ 10 9 \texttt{0} \le \texttt{start}_\texttt{i} < \texttt{end}_\texttt{i} \le \texttt{10}^\texttt{9} 0starti<endi109
  • end i < start i   +   1 \texttt{end}_\texttt{i} < \texttt{start}_\texttt{i + 1} endi<starti + 1
  • 0 ≤ start j < end j ≤ 10 9 \texttt{0} \le \texttt{start}_\texttt{j} < \texttt{end}_\texttt{j} \le \texttt{10}^\texttt{9} 0startj<endj109
  • end j < start j   +   1 \texttt{end}_\texttt{j} < \texttt{start}_\texttt{j + 1} endj<startj + 1

解法

思路和算法

由于给定的两个区间列表满足同一个区间列表中的区间各不相交且已经按升序排序,因此不需要处理区间合并,只需要从左到右同时遍历两个区间列表即可计算交集。

使用一个列表存储区间列表的交集。用 index 1 \textit{index}_1 index1 index 2 \textit{index}_2 index2 分别表示区间列表 firstList \textit{firstList} firstList secondList \textit{secondList} secondList 的下标,初始时 index 1 = index 2 = 0 \textit{index}_1 = \textit{index}_2 = 0 index1=index2=0

index 1 \textit{index}_1 index1 index 2 \textit{index}_2 index2 都未超出区间列表的下标范围时,同时遍历两个区间列表,记 interval 1 = firstList [ index 1 ] \textit{interval}_1 = \textit{firstList}[\textit{index}_1] interval1=firstList[index1] interval 2 = secondList [ index 2 ] \textit{interval}_2 = \textit{secondList}[\textit{index}_2] interval2=secondList[index2],记 start = max ⁡ ( interval 1 [ 0 ] , interval 2 [ 0 ] ) \textit{start} = \max(\textit{interval}_1[0], \textit{interval}_2[0]) start=max(interval1[0],interval2[0]) end = min ⁡ ( interval 1 [ 1 ] , interval 2 [ 1 ] ) \textit{end} = \min(\textit{interval}_1[1], \textit{interval}_2[1]) end=min(interval1[1],interval2[1]),执行如下操作。

  1. 如果 start ≤ end \textit{start} \le \textit{end} startend,则当前的两个区间 interval 1 \textit{interval}_1 interval1 interval 2 \textit{interval}_2 interval2 的交集为 [ start , end ] [\textit{start}, \textit{end}] [start,end],将 [ start , end ] [\textit{start}, \textit{end}] [start,end] 添加到交集列表中。如果 start > end \textit{start} > \textit{end} start>end,则当前的两个区间 interval 1 \textit{interval}_1 interval1 interval 2 \textit{interval}_2 interval2 的交集为空,不添加到交集列表中。

  2. 比较当前的两个区间 interval 1 \textit{interval}_1 interval1 interval 2 \textit{interval}_2 interval2 的末端,即 interval 1 [ 1 ] \textit{interval}_1[1] interval1[1] interval 2 [ 1 ] \textit{interval}_2[1] interval2[1],将末端较小的区间对应的下标向右移动一位。具体做法如下。

    • 如果 interval 1 [ 1 ] = interval 2 [ 1 ] \textit{interval}_1[1] = \textit{interval}_2[1] interval1[1]=interval2[1],则 interval 1 \textit{interval}_1 interval1 interval 2 \textit{interval}_2 interval2 都不可能和两个区间列表中的其余区间有交集,因此将 index 1 \textit{index}_1 index1 index 2 \textit{index}_2 index2 同时向右移动一位。

    • 如果 interval 1 [ 1 ] < interval 2 [ 1 ] \textit{interval}_1[1] < \textit{interval}_2[1] interval1[1]<interval2[1],则 interval 1 \textit{interval}_1 interval1 不可能和 secondList \textit{secondList} secondList 中的其余区间有交集,但是 interval 2 \textit{interval}_2 interval2 仍可能和 firstList \textit{firstList} firstList 中的其余区间有交集,因此将 index 1 \textit{index}_1 index1 向右移动一位。

    • 如果 interval 1 [ 1 ] > interval 2 [ 1 ] \textit{interval}_1[1] > \textit{interval}_2[1] interval1[1]>interval2[1],则 interval 2 \textit{interval}_2 interval2 不可能和 firstList \textit{firstList} firstList 中的其余区间有交集,但是 interval 1 \textit{interval}_1 interval1 仍可能和 secondList \textit{secondList} secondList 中的其余区间有交集,因此将 index 2 \textit{index}_2 index2 向右移动一位。

重复上述操作,直到 index 1 \textit{index}_1 index1 index 2 \textit{index}_2 index2 当中至少有一个下标超出区间列表的下标范围。如果一个下标超出区间列表的下标范围,则该下标所在的区间列表中的所有区间都已经被遍历过,因此不可能有更多的非空交集,此时得到完整的交集。

遍历结束之后,将列表转成数组返回。

代码

class Solution {
    public int[][] intervalIntersection(int[][] firstList, int[][] secondList) {
        List<int[]> intersectionList = new ArrayList<int[]>();
        int length1 = firstList.length, length2 = secondList.length;
        int index1 = 0, index2 = 0;
        while (index1 < length1 && index2 < length2) {
            int[] interval1 = firstList[index1];
            int[] interval2 = secondList[index2];
            int start = Math.max(interval1[0], interval2[0]);
            int end = Math.min(interval1[1], interval2[1]);
            if (start <= end) {
                intersectionList.add(new int[]{start, end});
            }
            if (interval1[1] <= interval2[1]) {
                index1++;
            }
            if (interval1[1] >= interval2[1]) {
                index2++;
            }
        }
        return intersectionList.toArray(new int[intersectionList.size()][]);
    }
}

复杂度分析

  • 时间复杂度: O ( m + n ) O(m + n) O(m+n),其中 m m m n n n 分别是区间列表 firstList \textit{firstList} firstList secondList \textit{secondList} secondList 的长度。双指针遍历两个区间列表各一次。

  • 空间复杂度: O ( m + n ) O(m + n) O(m+n),其中 m m m n n n 分别是区间列表 firstList \textit{firstList} firstList secondList \textit{secondList} secondList 的长度。存储区间交集的列表需要 O ( m + n ) O(m + n) O(m+n) 的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值