Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Example 1:
Input: intervals = [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].
Example 2:
Input: intervals = [[1,4],[4,5]] Output: [[1,5]] Explanation: Intervals [1,4] and [4,5] are considered overlapping.
Example 3:
Input: intervals = [[4,7],[1,4]] Output: [[1,7]] Explanation: Intervals [1,4] and [4,7] are considered overlapping.
Constraints:
1 <= intervals.length <= 104intervals[i].length == 20 <= starti <= endi <= 104Problem summary: Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array
[[1,3],[2,6],[8,10],[15,18]]
[[1,4],[4,5]]
[[4,7],[1,4]]
insert-interval)meeting-rooms)meeting-rooms-ii)teemo-attacking)add-bold-tag-in-string)import java.util.*;
class Solution {
public int[][] merge(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
List<int[]> merged = new ArrayList<>();
for (int[] cur : intervals) {
if (merged.isEmpty() || merged.get(merged.size() - 1)[1] < cur[0]) {
// No overlap: start a new interval.
merged.add(new int[] { cur[0], cur[1] });
} else {
// Overlap: extend the end of the current merged interval.
merged.get(merged.size() - 1)[1] =
Math.max(merged.get(merged.size() - 1)[1], cur[1]);
}
}
return merged.toArray(new int[merged.size()][]);
}
}
import "sort"
func merge(intervals [][]int) [][]int {
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0] < intervals[j][0]
})
merged := [][]int{}
for _, cur := range intervals {
if len(merged) == 0 || merged[len(merged)-1][1] < cur[0] {
merged = append(merged, []int{cur[0], cur[1]})
} else {
if cur[1] > merged[len(merged)-1][1] {
merged[len(merged)-1][1] = cur[1]
}
}
}
return merged
}
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:
intervals.sort(key=lambda x: x[0])
merged: List[List[int]] = []
for start, end in intervals:
if not merged or merged[-1][1] < start:
merged.append([start, end])
else:
merged[-1][1] = max(merged[-1][1], end)
return merged
impl Solution {
pub fn merge(intervals: Vec<Vec<i32>>) -> Vec<Vec<i32>> {
if intervals.is_empty() {
return vec![];
}
let mut intervals = intervals;
intervals.sort_by_key(|v| v[0]);
let mut merged: Vec<Vec<i32>> = vec![intervals[0].clone()];
for cur in intervals.into_iter().skip(1) {
let last = merged.last_mut().unwrap();
if cur[0] <= last[1] {
last[1] = last[1].max(cur[1]);
} else {
merged.push(cur);
}
}
merged
}
}
function merge(intervals: number[][]): number[][] {
intervals.sort((a, b) => a[0] - b[0]);
const merged: number[][] = [];
for (const cur of intervals) {
if (merged.length === 0 || merged[merged.length - 1][1] < cur[0]) {
merged.push([cur[0], cur[1]]);
} else {
merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], cur[1]);
}
}
return merged;
}
Use this to step through a reusable interview workflow for this problem.
Two nested loops check every pair or subarray. The outer loop fixes a starting point, the inner loop extends or searches. For n elements this gives up to n²/2 operations. No extra space, but the quadratic time is prohibitive for large inputs.
Most array problems have an O(n²) brute force (nested loops) and an O(n) optimal (single pass with clever state tracking). The key is identifying what information to maintain as you scan: a running max, a prefix sum, a hash map of seen values, or two pointers.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.