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
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.
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.
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.
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
| Approach | Time | Extra space | Notes |
|---|---|---|---|
| Repeated pairwise merging | O(nยฒ) per pass | O(n) | Easy to describe, hard to get right |
| Sort, then sweep | O(n log n) | O(n) for the output | The answer to code |
| Already sorted input | O(n) | O(n) for the output | Skip the sort if the interviewer guarantees order |
How to Talk Through It in an Interview
- Clarify: "Do touching intervals like [1, 2] and [2, 3] merge? Is the input sorted? Can I return a new list?"
- Brute force: "I could compare every pair and merge until nothing changes, but that is at least O(nยฒ)."
- Optimise: "If I sort by start, overlapping intervals become neighbours, so one pass is enough. The sort dominates at O(n log n)."
- Code: sort, seed the result, loop with one comparison. Say out loud why you use the maximum of the ends.
- 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?
Why do you sort intervals by start time?
Do touching intervals count as overlapping?
Why does my TypeScript merge intervals give the wrong order?
What problems use the same pattern?
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 →Still applying for jobs? Let Auto Apply do it for you.