Merge Intervals
Merge all overlapping intervals and return an array of non-overlapping intervals that cover all inputs. The definitive problem for mastering interval scheduling and sorting by start time.
Problem Statement
Given an array of intervals where intervals[i] = [start_i, end_i], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Examples & Constraints
- 1 <= intervals.length <= 10^4
- intervals[i].length == 2
- 0 <= start_i <= end_i <= 10^4
Sort by Start Time & Greedy Merge
Optimal ApproachSort intervals in ascending order by start time. Iterate through intervals: if the current interval starts before or at the previous end time, merge them by extending the end boundary.
Dominated by sorting the N intervals by start time. The subsequent linear merging pass takes O(n). Total runtime is O(n log n).
Consumes space to store the merged output list of intervals (and auxiliary sorting memory).
Underlying algorithmic logic
The Invariant: Chronological Start Times
When intervals are unsorted, determining whether two segments collide requires an expensive O(n²) comparison across all pairs.
However, if we sort intervals by their start time (start_i):
- Any interval that can possibly overlap with interval
Amust appear directly afterAin the sorted list!
The Greedy Merging Rule:
- Sort
intervalssuch thatintervals[i][0] <= intervals[i + 1][0]. - Initialize a merged list
resand append the first interval:res.append(intervals[0]). - For each subsequent interval
currinintervals[1..n-1]:
- Let
lastbe the most recently added interval inres. - Case 1: Overlap: If
curr.start <= last.end: - The intervals collide!
- Merge them by taking the maximum end boundary:
last.end = max(last.end, curr.end) - Case 2: No Overlap: If
curr.start > last.end: - There is a gap between
lastandcurr. currstarts a brand new independent interval!- Append
currtores.
- Return
res.
Step-by-step execution walkthrough
[[1, 3], [2, 6], [8, 10], [15, 18]]. Insert [1, 3] into merged list.
2 <= 3 (overlap!). Merge: end = max(3, 6) = 6. Update last interval to [1, 6].
8 > 6 (no overlap!). Append [8, 10] as new interval.
15 > 10 (no overlap!). Append [15, 18]. Finished.
- •Optimal O(n log n) runtime
- •Clean single-pass scan after sorting by start time
- •Mutates original ordering by requiring a start-time sort
Code Implementations
Ready-to-useCopy & paste production-ready solutions for Sort by Start Time & Greedy Merge in your language of choice
def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:if not intervals:return []intervals.sort(key=lambda x: x[0])merged = [intervals[0]]for current in intervals[1:]:last = merged[-1]if current[0] <= last[1]:last[1] = max(last[1], current[1])else:merged.append(current)return mergedif __name__ == "__main__":test1 = [[1, 3], [2, 6], [8, 10], [15, 18]]test2 = [[1, 4], [4, 5]]print("test1 merged:", merge_intervals(test1))print("test2 merged:", merge_intervals(test2))
Understand Array & Matrix Visually
Explore sequential element access, subsegment manipulations, insertion, deletion, and 2D grid matrix walks. Test live edge cases and watch memory state transitions step-by-step.
Frequently Asked Questions
Related Logic & Algorithm Problems
3Sum
Find all unique triplets in an array that sum up to zero. The premier problem for learning how to combine sorting with two-pointer inward scans to avoid cubic brute force.
Contains Duplicate
Determine if any value appears at least twice in an integer array. A foundational problem for mastering constant-time hash lookups vs sorting trade-offs.
Two Sum
Find the two numbers in an array that sum up to a target value. The quintessential problem for learning how to trade memory for speed using a Hash Map.