The “Merge Intervals” problem is a classic algorithmic challenge that involves taking a list of intervals, each defined by a start and end time, and combining any that overlap. The goal is to return a list of mutually exclusive (non-overlapping) intervals that covers the same ranges.
For example, given [[1, 3], [2, 6], [8, 10], [15, 18]]
, the output should be [[1, 6], [8, 10], [15, 18]]
.
This is because [1, 3]
and [2, 6]
overlap and can be merged into [1, 6]
, while the others remain untouched.
This problem is essential in many real-world applications, such as calendar scheduling, CPU task scheduling, genomic range queries, and spatial data indexing. Understanding how to efficiently merge intervals teaches you about sorting, greedy techniques, and handling ranges in ordered data structures.
The key insight is that intervals must be processed in a sorted order based on their start times. Sorting allows us to linearly scan and detect overlaps without checking every possible pair. Once sorted, we can use a greedy strategy to decide whether to extend an existing interval or start a new one.
merged
that will contain the final merged intervals.merged
is empty, or the current interval does not overlap with the last interval in merged
, simply append the current interval.merged
to be the maximum of its current end and the end of the current interval.
Input: [[1, 4], [4, 5]]
[1, 4]
, add to merged
.[4, 5]
. Since 4 ≤ 4
, they overlap — merge them into [1, 5]
.[[1, 5]]
Another input: [[1, 3], [2, 6], [8, 10], [15, 18]]
[1, 3]
and [2, 6]
→ [1, 6]
[8, 10]
does not overlap with [1, 6]
→ add as-is[15, 18]
is also non-overlapping → add[[1, 6], [8, 10], [15, 18]]
Though the greedy approach is optimal and elegant, there are other less efficient or less clean ways:
O(n²)
time.
Time Complexity: O(n log n) — This comes from sorting the intervals. The merge process afterward is linear.
Space Complexity: O(n) — Required for storing the output list.
The “Merge Intervals” problem is an elegant example of how sorting followed by a single pass can simplify what would otherwise be a complex task. It's a perfect introduction to greedy algorithms and interval processing, with applications across scheduling, memory allocation, and range simplification in real-world systems.