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:
0 <= A.length < 1000
0 <= B.length < 1000
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
類似題目:
參考資料:
https://leetcode.com/problems/interval-list-intersections/
https://leetcode.com/problems/interval-list-intersections/discuss/231108/C%2B%2B-O(n)-"merge-sort"