Given an array of intervals where intervals[i] = [starti, endi]
, merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Example 1:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].
Example 2:
Input: intervals = [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.
Constraints:
1 <= intervals.length <= 10^4
intervals[i].length == 2
0 <= starti <= endi <= 10^4
Can you implement a function to solve this problem efficiently?
One naive approach to merging overlapping intervals is to iterate through all possible pairs of intervals and check for overlap. If two intervals overlap, merge them and update the list of intervals. Repeat this process until no more overlaps are found.
Algorithm:
i
in the list of intervals:j
in the list of intervals (where j != i
):i
and j
overlap.i
and j
with the new merged interval and remove the old intervals.Time Complexity: O(n^3) in the worst case, where n is the number of intervals. This is because for each interval, we iterate through all other intervals, and in the worst case, we might have to repeat this process multiple times.
Space Complexity: O(1) if we modify the input list in place. Otherwise, O(n) if we create a new list to store the merged intervals.
This approach is inefficient and not recommended for large inputs.
A more efficient approach involves sorting the intervals based on their start times. After sorting, we can iterate through the sorted intervals and merge overlapping intervals in a single pass.
Algorithm:
Code (Python):
def merge(intervals):
intervals.sort(key=lambda x: x[0]) # Sort by start times
merged = []
for interval in intervals:
if not merged or interval[0] > merged[-1][1]:
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][1], interval[1])
return merged
Explanation:
intervals.sort(key=lambda x: x[0])
line sorts the input intervals in ascending order based on their start times. This is crucial for efficiently merging overlapping intervals.merged = []
line initializes an empty list to store the merged intervals.interval
in the sorted intervals
list. Inside the loop:
if not merged or interval[0] > merged[-1][1]:
This condition checks if the merged
list is empty or if the current interval
's start time is greater than the end time of the last interval in the merged
list. If either of these conditions is true, it means the current interval
does not overlap with the last merged interval, so we append it to the merged
list.else: merged[-1][1] = max(merged[-1][1], interval[1])
If the current interval
overlaps with the last interval in the merged
list, we merge them by updating the end time of the last interval in the merged
list to be the maximum of its current end time and the end time of the current interval
.merged
list, which contains the non-overlapping intervals that cover all the intervals in the input.Time Complexity: O(n log n) due to the sorting step, where n is the number of intervals. The merging step takes O(n) time.
Space Complexity: O(n) in the worst case, where n is the number of intervals. This is because in the worst case, none of the intervals overlap, and we need to store all of them in the merged list.
Edge Cases: