How do you merge overlapping time intervals in an array? Explain with examples and analyze time and space complexity.

2 years ago

You are given an array of time intervals (start, end) for meetings. Merge the overlapping intervals and return an array of non-overlapping intervals representing the consolidated meeting times. For example:

  1. Given the intervals [[1,3],[2,6],[8,10],[15,18]], the expected output is [[1,6],[8,10],[15,18]]. The intervals [1,3] and [2,6] overlap and are merged into [1,6].
  2. Given the intervals [[1,4],[4,5]], the expected output is [[1,5]]. The intervals [1,4] and [4,5] overlap and are merged into [1,5].
  3. Given the intervals [[1,4],[0,4]], the expected output is [[0,4]]. The intervals [1,4] and [0,4] overlap and are merged into [0,4].
  4. Given the intervals [[1,4],[0,2],[3,5]], the expected output is [[0,5]]. The intervals [1,4] and [0,2] overlap and are merged into [0,4]. Then [0,4] and [3,5] are merged into [0,5].

Explain your approach. Write a function that takes a list of intervals and returns a list of merged intervals. What is the time and space complexity of your solution?

Sample Answer

Merge Intervals

This problem involves merging overlapping intervals in a list. I'll start by explaining the approach, then provide a Python function to solve it, and finally analyze the time and space complexity.

Approach

  1. Sort the intervals: Sort the intervals based on the start time. This ensures that we process intervals in a sequential order, making it easier to identify overlaps.
  2. Merge overlapping intervals: Iterate through the sorted intervals and maintain a merged list. For each interval, check if it overlaps with the last interval in the merged list. If it does, merge them. If not, add the current interval to the merged list.

Python Function

def merge_intervals(intervals):
    if not intervals:
        return []

    # Sort the intervals based on the start time
    intervals.sort(key=lambda x: x[0])

    merged = []
    for interval in intervals:
        # If the merged list is empty or the current interval does not overlap
        # with the last interval in the merged list, append it
        if not merged or interval[0] > merged[-1][1]:
            merged.append(interval)
        else:
            # Otherwise, there is overlap, so we merge the current interval
            # with the last interval in the merged list
            merged[-1][1] = max(merged[-1][1], interval[1])

    return merged

# Example Usage:
intervals1 = [[1,3],[2,6],[8,10],[15,18]]
print(f"Input: {intervals1}, Merged: {merge_intervals(intervals1)}")

intervals2 = [[1,4],[4,5]]
print(f"Input: {intervals2}, Merged: {merge_intervals(intervals2)}")

intervals3 = [[1,4],[0,4]]
print(f"Input: {intervals3}, Merged: {merge_intervals(intervals3)}")

intervals4 = [[1,4],[0,2],[3,5]]
print(f"Input: {intervals4}, Merged: {merge_intervals(intervals4)}")

Time Complexity Analysis

  • Sorting: The dominant operation is sorting the intervals, which takes O(n log n) time, where n is the number of intervals.
  • Merging: Iterating through the sorted intervals and merging them takes O(n) time in the worst case.
  • Total: Therefore, the overall time complexity is O(n log n), primarily due to the sorting step.

Space Complexity Analysis

  • Merged list: In the worst case, if there are no overlapping intervals, the merged list will contain all the original intervals, resulting in O(n) space.
  • Sorting: The space complexity of the sorting algorithm depends on the implementation. Python's sort() method uses Timsort, which has a space complexity of O(n) in the worst case.
  • Total: Therefore, the overall space complexity is O(n).

Edge Cases

  1. Empty Input: If the input list of intervals is empty, the function should return an empty list.
  2. Single Interval: If the input list contains only one interval, the function should return a list containing that interval.
  3. Non-Overlapping Intervals: If the input list contains intervals that do not overlap, the function should return the list of intervals in sorted order.
  4. Completely Overlapping Intervals: If one interval completely contains another, the function should merge them correctly.
  5. Intervals with the same start time: The code handles intervals with the same start time correctly due to the sorting and merging logic.