Searching and sorting / Intervals / 039 · Sort and merge intervals

Sort and merge intervals

Sort by start; extend the current interval when the next one overlaps.

The invariant

The output is disjoint and sorted; the current interval may still grow.

01The intuition

Start with what you would do by hand

Four time slots: [1,3], [2,6], [8,10], [15,18]. Some overlap. Merge the overlapping ones into single slots. By eye, [1,3] and [2,6] touch, so they become [1,6]; the others stay. Answer: [1,6], [8,10], [15,18].

By hand with many slots, you would compare every pair to see if they overlap, merge, and repeat until nothing changes. For n slots that is n(n − 1)/2 pair checks per round, and a merge can create a new overlap, so several rounds. Messy and slow.

The mess comes from the slots being in random order. If they were in order of start time, an overlap could only happen between a slot and the one right before it, because everything earlier started even earlier.

Build the structure, one piece at a time

Piece 1: sort by start. [1,3], [2,6], [8,10], [15,18] happens to be sorted already.

Piece 2: one current slot. Keep a single slot that is still "open", meaning a later slot might extend it. Start with the first slot, [1,3].

Piece 3: the overlap test. Take the next slot [s, e]. If s ≤ the current slot's end, the two overlap: extend the current end to max(current end, e). Otherwise the current slot is finished: put it in the output and make the new slot the current one.

Next slotCurrent endOverlap?Current afterOutput so far
[1,3]nonestart[1,3]
[2,6]32 ≤ 3, yes[1,6]
[8,10]68 > 6, no[8,10][1,6]
[15,18]1015 > 10, no[15,18][1,6], [8,10]
end[1,6], [8,10], [15,18]

Why max(current end, e)? A slot like [2,4] after [1,6] overlaps but does not extend; the end must stay 6.

Why it is correct

The invariant: the output slots are disjoint, sorted, and final; the current slot covers every input slot seen so far that is not already in the output; and the current slot's start is at least the output's last end plus a gap.

Because the input is sorted by start, the next slot starts at or after the current slot's start. If it starts at or before the current end, it overlaps and merging keeps the current slot as one connected piece. If it starts after the current end, then every later slot also starts after the current end (they start even later), so nothing will ever touch the current slot again, and it is safe to output it.

sorted by start and snext > endcurrent ⇒ slater ≥ snext > endcurrent for every later slot

That one line is the whole proof: sorting turns "could any slot overlap this one" into "does the very next slot overlap this one".

Why it is fast

Sorting n slots costs O(n log n). The sweep looks at each slot once and does a comparison and a max, so O(n).

total = O(n log n) + O(n) = O(n log n)

For a million slots that is about twenty million steps for the sort, versus repeated rounds of five hundred billion pair checks.

How to recognise it in an interview

The cues are "merge", "overlapping intervals", "insert an interval", "free time between meetings", "summary ranges of consecutive numbers". Any input made of [start, end] pairs where the question is about unions or gaps. Say: "Sort by start; then only the previous interval can overlap the next one, so one sweep with a current interval does it."

Merge Intervals is the example above. Insert Interval is the same sweep where one of the slots is new; you can skip the sort if you walk the already-sorted list and merge the new slot in place. Summary Ranges treats consecutive integers as touching intervals of length one.

02The idea in one line

Sort by start; extend the current interval when the next one overlaps.

Reach for it when: Merge, insert interval, employee free time, summary ranges.

Cost: O(n log n) time.

03The walk-through, step by step

The video works one example: Merge Intervals on [[1,3],[2,6],[8,10],[15,18]]. These are its captions in order, so you can follow without the video or check a step you missed.

  1. Sort by start; walk left to right keeping one current interval
  2. [1,3] starts after the current end: start a new interval
  3. [2,6] starts at 2 ≤ 6: overlaps, extend the end to 6
  4. [8,10] starts after the current end: start a new interval
  5. [15,18] starts after the current end: start a new interval
  6. Done: [[1,6],[8,10],[15,18]], disjoint and sorted
  7. Sort O(n log n), then one linear sweep

04Asked at Google

9 Google-tagged LeetCode problems use this pattern. Frequency is LeetCode's Google-tag score (higher means reported more often); "last 6 months" marks problems reported in the most recent window of the export.

ProblemDifficultyFrequencyReported
Merge IntervalsMedium65last 6 months
Insert IntervalMedium45last 6 months
Range ModuleHard40last 6 months
Summary RangesEasy36last 6 months
Count Days Without MeetingsMedium31
Interval List IntersectionsMedium26
Employee Free TimeHard24last 6 months
Data Stream as Disjoint IntervalsHard8
Teemo AttackingEasy8

Other patterns in Intervals: Sweep line (events ±1), Earliest finish first.