You are given two lists of closed intervals, firstList
and secondList
, where firstList[i] = [starti, endi]
and secondList[j] = [startj, endj]
. Each list of intervals is pairwise disjoint and in sorted order.
Return the intersection of these two interval lists.
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 are either empty or represented as a closed interval. For example, the intersection of [1, 3]
and [2, 4]
is [2, 3]
.
Example 1:
Input: firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]] Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]
Example 2:
Input: firstList = [[1,3],[5,9]], secondList = [] Output: []
Constraints:
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
This problem asks to find the intersection of two lists of closed intervals. Both input lists are pairwise disjoint and sorted. The solution uses a two-pointer approach for optimal efficiency.
The core idea is to iterate through both lists simultaneously using two pointers, i
and j
, one for each list. At each step, we compare the current intervals from both lists:
Find the intersection: We calculate the start and end of the intersection by taking the maximum of the two interval starts (max(firstList[i][0], secondList[j][0])
) and the minimum of the two interval ends (min(firstList[i][1], secondList[j][1])
). If the resulting start is less than or equal to the end (meaning there's an intersection), we add this intersection interval to the result list.
Advance the pointers: We advance the pointer of the interval that ends sooner. This is because any further intersections with the interval that ended earlier will not overlap with the current interval from the other list since the lists are sorted.
Repeat: We continue this process until one of the pointers reaches the end of its respective list.
class Solution:
def intervalIntersection(
self, firstList: List[List[int]], secondList: List[List[int]]
) -> List[List[int]]:
i = j = 0
ans = []
while i < len(firstList) and j < len(secondList):
s1, e1, s2, e2 = *firstList[i], *secondList[j] # Unpack the intervals
l, r = max(s1, s2), min(e1, e2) # Calculate intersection start and end
if l <= r: # Check for intersection
ans.append([l, r]) # Add intersection to result
if e1 < e2: # Advance the pointer of the interval that ends sooner
i += 1
else:
j += 1
return ans
The Python code directly implements the algorithm described above. The *
operator unpacks the nested lists into individual variables for easier readability and manipulation.
firstList
and secondList
respectively. We iterate through each list at most once.ans
) is bounded by the length of the shorter input list, as the number of intersections cannot exceed the number of intervals in the smaller list. In the best case (no intersections), it's O(1).The approach remains consistent across different programming languages. The provided code snippets in Java, C++, Go, TypeScript, and Rust demonstrate this. The primary differences lie in syntax and data structure handling. For instance, Java and C++ use ArrayList
and vector
respectively to handle dynamic resizing of the result list.
Let's consider firstList = [[0,2],[5,10],[13,23],[24,25]]
and secondList = [[1,5],[8,12],[15,24],[25,26]]
.
i = 0, j = 0
: [0, 2]
and [1, 5]
intersect at [1, 2]
. e1 < e2
, so i
increments.i = 1, j = 0
: [5, 10]
and [1, 5]
intersect at [5, 5]
. e1 > e2
, so j
increments.i = 1, j = 1
: [5, 10]
and [8, 12]
intersect at [8, 10]
. e1 < e2
, so i
increments.i = 2, j = 1
: [13, 23]
and [8, 12]
do not intersect. e1 > e2
, so j
increments.i = 2, j = 2
: [13, 23]
and [15, 24]
intersect at [15, 23]
. e1 < e2
, so i
increments.i = 3, j = 2
: [24, 25]
and [15, 24]
intersect at [24, 24]
. e1 < e2
, so i
increments.i = 3, j = 3
: [24, 25]
and [25, 26]
intersect at [25, 25]
. The algorithm terminates.The final result is [[1, 2], [5, 5], [8, 10], [15, 23], [24, 24], [25, 25]]
.