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
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We have two groups of time slots, and need to find all the times when both groups are busy simultaneously. The brute force approach is like checking every possible pair of time slots, one from each group, to see if they overlap.
Here's how the algorithm would work step-by-step:
def interval_list_intersections_brute_force(first_list, second_list):
intersection_list = []
for first_interval in first_list:
for second_interval in second_list:
# Check if the intervals overlap
if (first_interval[1] >= second_interval[0] and
second_interval[1] >= first_interval[0]):
# Determine the start and end of intersection
intersection_start = max(first_interval[0], second_interval[0])
# Find the lower end time for the intersection
intersection_end = min(first_interval[1], second_interval[1])
# Append the intersection to the result list
intersection_list.append([intersection_start, intersection_end])
return intersection_list
To find the overlapping parts of two lists of time periods, the best way is to go through both lists in order, checking for overlaps as you go. We only need to look at each time period once, making it efficient.
Here's how the algorithm would work step-by-step:
def interval_intersection(first_list, second_list):
intersection_list = []
first_list_index = 0
second_list_index = 0
while first_list_index < len(first_list) and second_list_index < len(second_list):
first_interval_start, first_interval_end = first_list[first_list_index]
second_interval_start, second_interval_end = second_list[second_list_index]
# Check if the intervals overlap.
if first_interval_end >= second_interval_start and second_interval_end >= first_interval_start:
# Determine the start and end of the intersection.
intersection_start = max(first_interval_start, second_interval_start)
intersection_end = min(first_interval_end, second_interval_end)
intersection_list.append([intersection_start, intersection_end])
# Advance the pointer of the interval that ends sooner.
if first_interval_end < second_interval_end:
first_list_index += 1
# The current interval from the first list is fully processed.
else:
second_list_index += 1
# The current interval from the second list is fully processed.
return intersection_list
Case | How to Handle |
---|---|
Both input lists are empty | Return an empty list since there are no intervals to intersect. |
One input list is empty, the other is not | Return an empty list since no intersection is possible with an empty list. |
Intervals in firstList and secondList are disjoint (no intersection) | The algorithm should correctly identify the lack of overlap and return an empty list. |
Intervals in firstList are entirely contained within intervals of secondList (or vice versa) | The algorithm correctly finds the intersecting intervals, which would be the intervals of the smaller list in this scenario. |
Intervals have the same start or end point (touching) | The condition a[1] >= b[0] && b[1] >= a[0] must include equality to account for touching intervals and find the intersection, which could be a single point. |
Large number of intervals in both lists | The two-pointer approach ensures the algorithm has a time complexity of O(m+n), which scales linearly with the input sizes. |
Integer overflow if start/end points are very large | Use long data types or check for potential overflow before performing calculations to prevent incorrect results. |
Intervals with negative start/end values | The provided comparisons should correctly handle negative values for interval start and end points. |