You are given two lists of closed intervals, firstList
and secondList
, where firstList[i] = [start_i, end_i]
and secondList[j] = [start_j, end_j]
. 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:
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]]
Explain how to efficiently find the intersections of the intervals in the two lists. What is the time and space complexity of your solution? Consider edge cases such as empty lists or completely disjoint intervals.
A brute-force approach would involve iterating through all possible pairs of intervals, one from firstList
and one from secondList
, and checking if they intersect. If they do, compute the intersection and add it to the result.
def intervalIntersection_brute_force(firstList, secondList):
result = []
for i in range(len(firstList)):
for j in range(len(secondList)):
start1, end1 = firstList[i]
start2, end2 = secondList[j]
# Check for intersection
if start1 <= end2 and start2 <= end1:
intersection_start = max(start1, start2)
intersection_end = min(end1, end2)
result.append([intersection_start, intersection_end])
return result
firstList
and 'n' is the length of secondList
. This is because we are iterating through all possible pairs of intervals.A more efficient solution leverages the fact that both lists are sorted and disjoint. We can use a two-pointer approach. We maintain two pointers, one for each list, and advance the pointers based on the interval endpoints.
i
and j
, to 0 for firstList
and secondList
respectively.i
and j
are within the bounds of their respective lists:
start1
, end1
be the start and end of firstList[i]
and start2
, end2
be the start and end of secondList[j]
.intersection_start = max(start1, start2)
and intersection_end = min(end1, end2)
.intersection_start <= intersection_end
, then an intersection exists. Add [intersection_start, intersection_end]
to the result.end1 < end2
, increment i
. Otherwise, increment j
.def intervalIntersection(firstList, secondList):
result = []
i, j = 0, 0
while i < len(firstList) and j < len(secondList):
start1, end1 = firstList[i]
start2, end2 = secondList[j]
# Compute intersection
intersection_start = max(start1, start2)
intersection_end = min(end1, end2)
if intersection_start <= intersection_end:
result.append([intersection_start, intersection_end])
# Advance the pointer of the interval that ends earlier
if end1 < end2:
i += 1
else:
j += 1
return result
firstList
and 'n' is the length of secondList
. This is because, in the worst case, we iterate through both lists once.firstList
or secondList
is empty, the intersection is empty. The algorithm handles this correctly because the while
loop condition will be false immediately.