[LeetCode] 986. Interval List Intersections 區間列表的交集



Given two lists of closed intervals, each list of intervals is pairwise disjoint and in sorted order.

Return the intersection of these two interval lists.

(Formally, a closed interval [a, b] (with a <= b) denotes the set of real numbers x with a <= x <= b.  The intersection of two closed intervals is a set of real numbers that is either empty, or can be represented as a closed interval.  For example, the intersection of [1, 3] and [2, 4] is [2, 3].)

Example 1:

Input: A = [[0,2],[5,10],[13,23],[24,25]], B = [[1,5],[8,12],[15,24],[25,26]]
Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

Note:

  1. 0 <= A.length < 1000
  2. 0 <= B.length < 1000
  3. 0 <= A[i].start, A[i].end, B[i].start, B[i].end < 10^9

這道題給了兩個區間數組,讓返回所有相交的區間組成的數組。題目中的例子很貼心的還配了圖,可以很直觀的看出來相交的區間,而且可以注意到題目允許起始和結束位置相同的區間。這種類似合並區間的問題之前也做過 Merge Intervals,但是那道是只有一個區間數組進行合並,而這道題給了兩個區間數組找相交區間,其實問題的本質都一樣。對於這道題,由於求相交區間是要兩兩進行比較的,所以比較好的解法就是使用雙指針來做,分別指向A和B中的某一個區間。這里用i和j兩個變量表示,初始化為0,進行 while 循環,循環條件是i和j均沒有遍歷到末尾,然后來考慮,假如兩個區間沒有交集,就不用進行操作,直接平移指針即可。若i指向的區間在左邊,即 A[i][1] < B[j][0] 時,i自增1,若j指向的區間在左邊,即 B[j][1] < A[i][0] 時,j自增1,否則就是有交集,求交集的方法也簡單,就是兩個區間的起始位置中的較大值,和結束位置中的較小值組成的。將相交區間加入結果 res 后,還要平移指針,此時看,若i指向的區間結束位置小,則i自增1,若j指向的區間結束位置小,則j自增1,若二者相同,則i和j均自增1。這樣循環退出后,所有的相交區間就保存在結果 res 中了,參見代碼如下:


解法一:

class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& A, vector<vector<int>>& B) {
        int m = A.size(), n = B.size(), i = 0, j = 0;
        vector<vector<int>> res;
        while (i < m && j < n) {
            if (A[i][1] < B[j][0]) {
                ++i;
            } else if (B[j][1] < A[i][0]) {
                ++j;
            } else {
                res.push_back({max(A[i][0], B[j][0]), min(A[i][1], B[j][1])});
                if (A[i][1] < B[j][1]) ++i;
                else if (B[j][1] < A[i][1]) ++j;
                else {++i; ++j;}
            }
        }
        return res;
    }
};

我們也可以再寫的簡潔一些,其實並不用單獨處理不相交的情況,只要分別求出兩個區間起始位置的較大值,和結束位置的較小值,只要當前者小於等於后者時,相交區間才存在,此時才需要加入結果 res 中,然后還是根據兩個區間結束位置的大小關系來平移指針,這樣的寫法就簡潔多了,參見代碼如下:


解法二:

class Solution {
public:
    vector<vector<int>> intervalIntersection(vector<vector<int>>& A, vector<vector<int>>& B) {
        int m = A.size(), n = B.size(), i = 0, j = 0;
        vector<vector<int>> res;
        while (i < m && j < n) {
            int lo = max(A[i][0], B[j][0]), hi = min(A[i][1], B[j][1]);
            if (lo <= hi) res.push_back({lo, hi});
            (A[i][1] < B[j][1]) ? ++i : ++j;
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/986


類似題目:

Merge Intervals

Merge Sorted Array

Employee Free Time


參考資料:

https://leetcode.com/problems/interval-list-intersections/

https://leetcode.com/problems/interval-list-intersections/discuss/231108/C%2B%2B-O(n)-"merge-sort"

https://leetcode.com/problems/interval-list-intersections/discuss/646988/C%2B%2B-or-Easy-or-6-lines-or-Two-pointer-or-100


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM