We're given a list of intervals, each with a start and end value, and we need to combine any intervals that overlap. Two intervals overlap when one starts before the other ends. For instance, [1,3] and [2,6] overlap because 2 is between 1 and 3. The merged result would be [1,6], taking the minimum start and maximum end.
A critical detail: intervals that share exactly one endpoint also overlap. [1,4] and [4,5] merge into [1,5] because the end of the first equals the start of the second.
The challenge is not detecting overlap between two intervals. It is efficiently figuring out which intervals overlap when there could be thousands of them. If the intervals were sorted by start time, overlapping intervals would always be adjacent, which is what the optimal solution exploits.
1 <= intervals.length <= 10^4 → With n up to 10,000, O(n^2) is 100 million operations, which is borderline. O(n log n) is comfortably within limits.0 <= start_i <= end_i <= 10^4 → Starts are always less than or equal to ends, so no need to handle invalid intervals. Values are non-negative and bounded.intervals[i].length == 2 → Every interval has exactly two elements. No degenerate inputs.For every pair of intervals, check if they overlap. If they do, combine them into one interval that spans both, then restart the search. Repeat until a full scan finds no overlapping pair.
A single merge can create new overlaps that did not exist before. Merging [1,3] with [4,6] would not, but merging [1,3] with [2,8] produces [1,8], which might now overlap with an interval that [1,3] did not reach. Restarting after each merge handles this at the cost of repeated work: each merge removes one interval, so the input can require up to n merge passes, and each pass scans all pairs.
merged to track whether any merge happened in the current pass.(i, j), check if they overlap (one's start is within the other's range).i with the merged result and remove interval j.merged = true and restart the inner loop (since indices shifted).The repeated pairwise comparisons on unsorted data are the bottleneck. Sorting the intervals first makes overlapping intervals adjacent, which removes the need to compare every pair.
Sort the intervals by start time, and any group of overlapping intervals becomes a contiguous run in the sorted order. Once sorted, a single left-to-right scan can merge each run as it appears.
The scan keeps one current merged interval. For each next interval, its start is greater than or equal to the current interval's start because of the sort. So the two overlap exactly when the next start is less than or equal to the current end. When they overlap, extend the current end. When they do not overlap, the current interval can never overlap any later interval, since every later start is at least the current next start, which already exceeds the current end. So the current interval is finalized and the next interval becomes the new current one.
When extending, the new end is max(currentEnd, nextEnd), not nextEnd. An interval like [1,10] fully contains [2,5], so the merged end must stay at 10, not shrink to 5.
max(lastEnd, currentEnd).