2Brute2Best
🔥0

Merge Intervals

Medium·LeetCode #56Basic Anchor
LeetCode
30-Second Mental ModelIntervals — Merge overlaps
Complexity:O(N³)→O(N log N)
Key Insight

Sort by start. Walk through the intervals keeping a list merged. If the current interval starts at or before the end of merged.back(), it overlaps that group: stretch the group's end to max(end, cur.end). Otherwise it starts a new group.

Core Validity Invariant

cur joins the last group if and only if cur.start ≤ merged.back().end.

01

Problem

You get a list of intervals. Each one is [start, end] and includes both ends.

If two intervals overlap, join them into one bigger interval. Keep doing this until no two intervals overlap. Return the final list.

Intervals that only touch (one ends exactly where the next starts, like [1,4] and [4,5]) also count as overlapping and must be joined.

Input

A list intervals, where intervals[i] = [start, end].

Output

The merged intervals, with no two overlapping. Any order is accepted.

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

[1,3] and [2,6] overlap (2 is inside [1,3]), so they become [1,6]. The other two don't touch anything.

Example 2
Input: intervals = [[1,4],[4,5]]
Output: [[1,5]]

They share the point 4, which counts as overlapping.

Example 3
Input: intervals = [[4,7],[1,4]]
Output: [[1,7]]

The input is not sorted. [1,4] and [4,7] touch at 4, so they join.

Constraints
  • • 1 ≤ intervals.length ≤ 10^4
  • • intervals[i].length == 2
  • • 0 ≤ start ≤ end ≤ 10^4
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    When exactly do two intervals [a, b] and [c, d] overlap? Write the test with ≤ or < and check it on touching intervals.

  2. 2.

    If the input were sorted by start, where would the intervals that overlap a given one be?

  3. 3.

    When I join two intervals, what is the new start and the new end?

  4. 4.

    Can one interval sit completely inside another? What happens to the end then?

  5. 5.

    Once an interval starts after my current group ends, can any later interval still join that group?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceScan all pairs, merge the first overlapping pair found, repeatO(N³)O(N)
OptimalSort by start; each interval either stretches the last group or starts a new oneO(N log N)O(N)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “list of [start, end] intervals”Interval problem → think about sorting by start or by end.
  • “merge all overlapping”Groups of intervals that chain together. After sorting by start, a group is a run of neighbours.
  • “any order is fine”We are free to sort the input; nothing depends on the original order.
[start, end] pairs+join overlaps+sort by start, compare with the last group→Intervals — Merge overlaps

This is the anchor for the whole Merge sub-pattern: sort by start, keep one running group, and decide with a single test cur.start ≤ end. The next questions change only small parts: Insert Interval skips the sort because the input is already sorted, Remove Covered Intervals changes the test to containment, and Count Days Without Meetings adds up the merged lengths.

10

Don't make this mistake

Comparing with intervals[i − 1] instead of the last merged interval
✗ if (intervals[i][0] <= intervals[i - 1][1]) ...
✓ if (cur[0] <= merged.back()[1]) ...

The previous interval can be short while the group is long. In [1,10], [2,3], [5,6], the interval [5,6] does not overlap [2,3], but it does overlap the group [1,10]. Always compare with the group, not the neighbour.

Setting end = cur.end instead of the max
✗ merged.back()[1] = cur[1];
✓ merged.back()[1] = max(merged.back()[1], cur[1]);

An interval can sit completely inside the group. With [1,6], [4,5], writing end = 5 shrinks the group, and a later [6,7] would wrongly become its own group.

Using < instead of ≤ for the overlap test
✗ if (cur[0] < merged.back()[1])
✓ if (cur[0] <= merged.back()[1])

Here touching intervals like [1,4] and [4,5] must join. With < they stay apart.

Pattern confusion: sorting by end

Sorting by end is the trick for the Coverage sub-pattern (Non-overlapping Intervals, Arrows), where you greedily keep the earliest finisher. For merging, sort by start: a long interval like [1,10] sorted by end comes after [2,3] and [5,6]. Those two become separate groups first, then [1,10] only joins the last one, giving the wrong answer [[2,3],[5,10]] instead of [[1,10]].

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Intervals translate into production architectures and low-level memory mechanics.