Pattern 1: Sort and merge
Merging overlapping intervals is the "hello, world" of the section. And it shows, in its purest form, the method that works for almost everything here: sort by start, then scan once.
Try it first: Merge Intervals
Before reading the theory, try to solve it. You can start with brute force, you can fail — the point is to feel the problem. The theory comes right below.
Given a list of intervals [start, end], merge all the overlapping ones and return the resulting list (sorted by start).
Example: [[1,3],[2,6],[8,10],[15,18]] → [[1,6],[8,10],[15,18]] ([1,3] and [2,6] overlap → [1,6]).
Tried it? Without sorting, you end up comparing each interval against all the others (O(n²)) and still get lost with chained overlaps. The theory below shows why sorting first makes everything simple.
The theory: sorting transforms the problem
Why does sorting by start help so much? Because, after that, any interval that overlaps a previous one can only overlap the last one you processed (all the earlier ones already ended further to the left). This reduces "compare with all" to "compare with the last one in the result":
sort by start
result = []
for each [start, end]:
if result not empty AND start <= end of last in result:
# overlaps → extend the end of the last
last.end = max(last.end, end)
else:
# no overlap → start a new block
result.append([start, end])
Note the max when extending: the current interval may be contained in
the last one (e.g., [1,6] swallowing [2,4]), so the end must not shrink.
Watch the scan — the top row is the input (current one highlighted), the
bottom row is the result being built and extended:
Why is it O(n log n) time and O(n) space?
The sort costs O(n log n) and dominates. The scan is a single O(n) pass, comparing each interval only with the last one in the result. Space is O(n) for the output list (or O(log n)–O(n) for the sort itself). The brute force of comparing all pairs would be O(n²) — sorting is what knocks that down.
The reflex that defines the section
This is the mother template of intervals: sort by one endpoint + one scan comparing against the accumulated state. Memorize the shape of the code — the next lessons are variations of it (insert changes "when to start merging," the greedy one changes the sorting criterion, the event sweep changes what you accumulate).
🧠 Review quiz
0/41. Why does sorting by start simplify merging intervals?
2. When merging an overlapping interval, why use max(last.end, current.end) instead of just current.end?
3. What is the complexity of merge and what dominates it?
4. What is the 'mother template' of interval problems, of which merge is the example?
Summary
- Merge: sort by start; scan, merging when
start <= end of the last(withmaxon the end). - O(n log n) (sort dominates), O(n) space; far better than the naive O(n²).
- It's the mother template of the section: sort + scan with accumulated state.
Next lesson: insert an interval into a set that's already sorted.