Find the bug · Medium
Fix Merge Intervals
Medium Find the bug Most askedSeen at Meta, Google, Bloomberg
merge(intervals) merges all overlapping intervals and returns them sorted by start. Intervals that only touch ([1, 2] and [2, 3]) also merge.
The code sorts correctly and handles the common case, but loses data for some inputs. Find the bug and fix it.
Example 1
Input: intervals = [[1, 3], [2, 6], [8, 10], [15, 18]] Output: [[1, 6], [8, 10], [15, 18]]
Example 2
Input: intervals = [[1, 4], [2, 3]] Output: [[1, 4]] Explanation: The buggy version returns [[1, 3]].
The buggy code
function merge(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
const out = [];
for (const cur of intervals) {
const last = out[out.length - 1];
if (last && cur[0] <= last[1]) last[1] = cur[1];
else out.push([...cur]);
}
return out;
}
function merge(intervals: number[][]): number[][] {
intervals.sort((a, b) => a[0] - b[0]);
const out: number[][] = [];
for (const cur of intervals) {
const last = out[out.length - 1];
if (last && cur[0] <= last[1]) last[1] = cur[1];
else out.push([...cur]);
}
return out;
}
def merge(intervals: list[list[int]]) -> list[list[int]]:
out: list[list[int]] = []
for cur in sorted(intervals):
if out and cur[0] <= out[-1][1]:
out[-1][1] = cur[1]
else:
out.append(list(cur))
return out
<?php
function merge(array $intervals): array
{
usort($intervals, fn ($a, $b) => $a[0] <=> $b[0]);
$out = [];
foreach ($intervals as $cur) {
$k = count($out) - 1;
if ($k >= 0 && $cur[0] <= $out[$k][1]) {
$out[$k][1] = $cur[1];
} else {
$out[] = $cur;
}
}
return $out;
}
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
List<int[]> out = new ArrayList<>();
for (int[] cur : intervals) {
if (!out.isEmpty() && cur[0] <= out.get(out.size() - 1)[1]) {
out.get(out.size() - 1)[1] = cur[1];
} else {
out.add(new int[]{cur[0], cur[1]});
}
}
return out.toArray(new int[0][]);
}
}
Hints
Hint 1
What happens when the current interval lies completely inside the previous one?
Find and fix the bug
Loading the editor… (JavaScript is required to run code in your browser.)
Solution and explanation
Show the bug and the fix
Time O(n log n) · Space O(n)
The bug: when the current interval overlaps the last merged one, the code sets the end to cur[1]. If the current interval is contained in the previous one ([2, 3] inside [1, 4]), that shrinks the merged interval.
The fix: extend to the larger end: last[1] = max(last[1], cur[1]).
Fixed version
function merge(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
const out = [];
for (const cur of intervals) {
const last = out[out.length - 1];
if (last && cur[0] <= last[1]) last[1] = Math.max(last[1], cur[1]);
else out.push([...cur]);
}
return out;
}
function merge(intervals: number[][]): number[][] {
intervals.sort((a, b) => a[0] - b[0]);
const out: number[][] = [];
for (const cur of intervals) {
const last = out[out.length - 1];
if (last && cur[0] <= last[1]) last[1] = Math.max(last[1], cur[1]);
else out.push([...cur]);
}
return out;
}
def merge(intervals: list[list[int]]) -> list[list[int]]:
out: list[list[int]] = []
for cur in sorted(intervals):
if out and cur[0] <= out[-1][1]:
out[-1][1] = max(out[-1][1], cur[1])
else:
out.append(list(cur))
return out
<?php
function merge(array $intervals): array
{
usort($intervals, fn ($a, $b) => $a[0] <=> $b[0]);
$out = [];
foreach ($intervals as $cur) {
$k = count($out) - 1;
if ($k >= 0 && $cur[0] <= $out[$k][1]) {
$out[$k][1] = max($out[$k][1], $cur[1]);
} else {
$out[] = $cur;
}
}
return $out;
}
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
List<int[]> out = new ArrayList<>();
for (int[] cur : intervals) {
if (!out.isEmpty() && cur[0] <= out.get(out.size() - 1)[1]) {
int[] last = out.get(out.size() - 1);
last[1] = Math.max(last[1], cur[1]);
} else {
out.add(new int[]{cur[0], cur[1]});
}
}
return out.toArray(new int[0][]);
}
}
Common mistakes
- Using
<instead of<=for touching intervals. - Sorting by end instead of start.
More Code Clinic: Find the Bug problems
- Fix the Binary Search · Easy
- Fix the Two Sum Hash Map · Easy
- Fix the Longest Substring Without Repeats · Medium
- Fix the Mutable Default Argument · Easy
- Fix the Substring Check · Easy
- Fix the Median (JavaScript Sort) · Easy