Taro Logo

Merge Intervals

Medium
Netflix logo
Netflix
7 views
Topics:
ArraysGreedy Algorithms

You are given a list of time intervals represented as an array of arrays, where each inner array contains the start and end time of an interval. The goal is to merge all overlapping intervals and return a new array containing only the non-overlapping intervals that completely cover all the original intervals.

For example:

  • Input: intervals = [[1,3],[2,6],[8,10],[15,18]]

  • Output: [[1,6],[8,10],[15,18]]

    • Explanation: The intervals [1,3] and [2,6] overlap, so they are merged into [1,6]. The other intervals do not overlap, so they remain as they are.
  • Input: intervals = [[1,4],[4,5]]

  • Output: [[1,5]]

    • Explanation: The intervals [1,4] and [4,5] overlap and are merged into [1,5].

Write a function that takes an array of intervals as input and returns an array of merged, non-overlapping intervals. Consider edge cases such as an empty input array or a list of intervals that are already merged or do not overlap.

Constraints:

  • 1 <= intervals.length <= 10^4
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 10^4

Solution


Naive Approach (Brute Force)

One simple way to approach this problem is to iterate through each interval and compare it with every other interval to see if they overlap. If two intervals overlap, merge them. Repeat this process until no more intervals can be merged.

This approach is not efficient but easy to understand.

Algorithm:

  1. For each interval in the list.
  2. Compare it with all other intervals.
  3. If they overlap, merge them and update the list.
  4. Repeat until no more merges are possible.

Big O Analysis

  • Time Complexity: O(n^3). In the worst case, each interval might need to be compared with every other interval multiple times.
  • Space Complexity: O(1). We're modifying the list in-place (excluding the space needed to store the input).

Optimal Approach (Sorting and Merging)

A more efficient approach involves sorting the intervals based on their start times. After sorting, you can iterate through the intervals and merge overlapping intervals in a single pass.

Algorithm

  1. Sort: Sort the intervals based on the start times.
  2. Merge:
    • Initialize an empty list called mergedIntervals.
    • Add the first interval to mergedIntervals.
    • Iterate through the remaining intervals:
      • If the current interval overlaps with the last interval in mergedIntervals, merge them.
      • Otherwise, add the current interval to mergedIntervals.
  3. Return mergedIntervals.

Edge Cases

  • Empty Input: If the input list of intervals is empty, return an empty list.
  • Non-Overlapping Intervals: If there are no overlapping intervals, the algorithm should return the original intervals (in sorted order).
  • Already Merged: If the intervals are already merged return the intervals as is.

Big O Analysis

  • Time Complexity: O(n log n). Sorting the intervals takes O(n log n) time, and the merging process takes O(n) time.
  • Space Complexity: O(n) in the worst case, where no intervals overlap, and we need to store all intervals in the merged list. O(1) if sorting in place.

Code (Python)

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

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

    merged = []
    for interval in intervals:
        # If the list of merged intervals is empty or if the current
        # interval does not overlap with the last interval, 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 one
            merged[-1][1] = max(merged[-1][1], interval[1])

    return merged