Jump to section

Merge intervals asks you to combine every overlapping range in a list into one, returning the smallest set of non-overlapping ranges. The standard answer is to sort by start time, then sweep once, extending the last merged interval or starting a new one. It runs in O(n log n) time because of the sort, with O(n) space for the output.

The Problem

You get a list of intervals, each a pair [start, end]. Some of them overlap. Return a list where every group of overlapping intervals has been combined into one interval that covers the whole group, and no two intervals in the result overlap.

Example 1

Input: [[9, 12], [1, 4], [3, 6], [8, 9]]. Output: [[1, 6], [8, 12]]. [1, 4] and [3, 6] overlap, so they become [1, 6]. [8, 9] and [9, 12] touch at 9, which this version counts as overlapping.

Example 2

Input: [[1, 10], [2, 3], [4, 5]]. Output: [[1, 10]]. The first interval swallows the other two completely. This is why you take the maximum of the two end values instead of just copying the new end.

Assumptions to confirm

  • Do intervals that only touch, like [1, 2] and [2, 3], count as overlapping? Ask, because it changes <= to <.
  • Is the input already sorted? Usually not.
  • May you change the input list, or should you return a new one? The solutions below leave the input untouched.

Brute Force First

A naive approach compares every pair of intervals and merges any two that overlap, then repeats until nothing changes. Each pass is O(nยฒ), and you may need several passes, so it is slow and fiddly to get right. Mention it briefly, then point out the key insight: once intervals are sorted by start, any interval can only overlap the one you merged just before it.

Ready to put this into practice?

Practice this with MockIF →

Still applying for jobs? Let Auto Apply do it

The Optimal Approach: Sort, Then Sweep

1

Sort by start time

After sorting, overlapping intervals sit next to each other. This is the step that costs O(n log n) and makes everything else linear.

2

Start the result with the first interval

Copy it rather than reusing the original, so you do not change the caller's data when you extend it.

3

Compare each interval with the last merged one

If its start is at or before the last end, they overlap: set the last end to the larger of the two ends.

4

Otherwise start a new block

If it starts after the last end, there is a gap, so append it as a new interval.

Python and TypeScript Solutions

Python

def merge_intervals(intervals: list[list[int]]) -> list[list[int]]:
    if not intervals:
        return []
    intervals = sorted(intervals, key=lambda iv: iv[0])
    merged = [intervals[0][:]]
    for start, end in intervals[1:]:
        last = merged[-1]
        if start <= last[1]:          # overlaps (or touches) the last block
            last[1] = max(last[1], end)
        else:
            merged.append([start, end])
    return merged

TypeScript

function mergeIntervals(intervals: number[][]): number[][] {
  if (intervals.length === 0) return [];
  const sorted = [...intervals].sort((a, b) => a[0] - b[0]);
  const merged: number[][] = [[...sorted[0]]];
  for (const [start, end] of sorted.slice(1)) {
    const last = merged[merged.length - 1];
    if (start <= last[1]) {
      last[1] = Math.max(last[1], end); // overlaps (or touches) the last block
    } else {
      merged.push([start, end]);
    }
  }
  return merged;
}

In TypeScript, pass a comparator to sort. Without one, JavaScript sorts arrays as strings, so [10, 12] would come before [9, 11]. That bug is a favourite follow-up question.

Ready to put this into practice?

Practice this with MockIF →

Still applying for jobs? Let Auto Apply do it

Complexity Compared

ApproachTimeExtra spaceNotes
Repeated pairwise mergingO(nยฒ) per passO(n)Easy to describe, hard to get right
Sort, then sweepO(n log n)O(n) for the outputThe answer to code
Already sorted inputO(n)O(n) for the outputSkip the sort if the interviewer guarantees order

How to Talk Through It in an Interview

  1. Clarify: "Do touching intervals like [1, 2] and [2, 3] merge? Is the input sorted? Can I return a new list?"
  2. Brute force: "I could compare every pair and merge until nothing changes, but that is at least O(nยฒ)."
  3. Optimise: "If I sort by start, overlapping intervals become neighbours, so one pass is enough. The sort dominates at O(n log n)."
  4. Code: sort, seed the result, loop with one comparison. Say out loud why you use the maximum of the ends.
  5. Test: run the nested case [[1, 10], [2, 3]], a single interval, an empty list and two intervals with a gap.

Ready to put this into practice?

Practice this with MockIF →

Still applying for jobs? Let Auto Apply do it

Edge Cases and Follow-Ups

One interval inside another

Taking the maximum end keeps [1, 10] when [2, 3] arrives. Copying the new end would shrink it to [1, 3].

Empty input

Return an empty list before touching index 0.

Follow-up: insert a new interval into a sorted list

You can do it in O(n) without re-sorting: copy intervals that end before the new one, merge the ones that overlap it, then copy the rest.

Follow-up: minimum meeting rooms

A related question: sort start and end times separately, or use a min-heap of end times. See the heapify guide for how heaps work.

Follow-up: intervals arriving in a stream

Keep them in a balanced tree or sorted structure keyed by start, and merge with neighbours on each insert.

Practise It in a Mock Coding Round

Reading a solution is not the same as producing it with someone watching. In a real round you have to clarify the problem, say the brute force out loud, and keep talking while you type. MockIF runs coding rounds with a voice AI interviewer in a real in-browser editor, in Python and TypeScript. It runs your code against tests, asks you to explain your approach, follows up on edge cases and complexity, then scores the round and gives you specific feedback. A session costs 2 credits. It is free to start with 5 credits, then monthly or 3-monthly plans, or one-off credit packs (see pricing). Read more about how a mock coding interview works.

Frequently Asked Questions

What is the time complexity of merge intervals?
O(n log n), because of sorting. The merge pass itself is O(n). If the input is already sorted, the whole thing is O(n).
Why do you sort intervals by start time?
Sorting puts overlapping intervals next to each other, so each one only needs comparing with the last merged interval instead of every other interval.
Do touching intervals count as overlapping?
It depends on the problem. With closed intervals, [1, 2] and [2, 3] share the point 2 and are usually merged. Ask the interviewer and switch between <= and < accordingly.
Why does my TypeScript merge intervals give the wrong order?
Array.prototype.sort compares items as strings by default. Pass a comparator such as (a, b) => a[0] - b[0] so intervals sort numerically by start.
What problems use the same pattern?
Insert interval, meeting rooms, non-overlapping intervals and interval list intersections all build on sorting by start and sweeping once.

Stop Preparing in Your Head. Start Practicing Out Loud.

Drop your resume, add a job description, and get a mock interview like the real thing.

Start Free Mock Interview →
No credit card required. 5 free credits to start.

Still applying for jobs? Let Auto Apply do it for you.

Try Auto Apply →