Quick Overview

A coding question that merges an unsorted list of closed integer intervals into disjoint intervals sorted by start. Intervals that overlap or merely touch at an endpoint must be combined, so it tests exact endpoint semantics, transitive merges, and nested or duplicate intervals.

Merge Overlapping Closed Intervals Into a Sorted Disjoint List

Company: Furtherai

Role: Machine Learning Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

Given a list of closed integer intervals, merge every group of overlapping intervals and return the resulting disjoint intervals. ### Function Signature ```python def merge_intervals(intervals: list[list[int]]) -> list[list[int]]: ``` Each interval is `[start, end]` with `start <= end`, and it contains every point from `start` to `end`, inclusive. ### Rules - The input may be in any order, and it may contain duplicate intervals and intervals nested inside others. - Two intervals overlap when they share at least one point. Intervals that only touch, such as `[1, 3]` and `[3, 5]`, share the point 3 and must be merged into `[1, 5]`. The intervals `[1, 2]` and `[3, 4]` share no point and stay separate. - Merging is transitive: if A overlaps B and B overlaps C, all three become one interval, even when A and C do not overlap. - Return the merged intervals sorted by `start` in ascending order. No two returned intervals share a point, and together they cover exactly the points covered by the input. ### Constraints - `1 <= len(intervals) <= 10^5` - `-10^9 <= start <= end <= 10^9` ### Examples **Example 1** ```text Input: intervals = [[8, 10], [1, 4], [3, 6], [12, 12]] Output: [[1, 6], [8, 10], [12, 12]] ``` `[1, 4]` and `[3, 6]` overlap on 3 to 4 and become `[1, 6]`. `[8, 10]` and the single point `[12, 12]` overlap nothing. **Example 2** ```text Input: intervals = [[1, 3], [3, 5], [6, 7]] Output: [[1, 5], [6, 7]] ``` `[1, 3]` and `[3, 5]` touch at 3, so they merge. `[1, 5]` and `[6, 7]` share no point. **Example 3** ```text Input: intervals = [[2, 9], [3, 4], [5, 5], [1, 2]] Output: [[1, 9]] ``` `[3, 4]` and `[5, 5]` lie inside `[2, 9]`, and `[1, 2]` touches it at 2.

Overview: A coding question that merges an unsorted list of closed integer intervals into disjoint intervals sorted by start. Intervals that overlap or merely touch at an endpoint must be combined, so it tests exact endpoint semantics, transitive merges, and nested or duplicate intervals.

Read the full Furtherai Machine Learning Engineer interview experience this question came from

Given a list `intervals` of closed integer intervals, merge every group of overlapping intervals and return the resulting disjoint intervals. Each interval is a pair `[start, end]` with `start <= end`, and it contains every point from `start` to `end`, inclusive. ### Rules - The input may be in any order, and it may contain duplicate intervals and intervals nested inside others. - Two intervals overlap when they share at least one point. Intervals that only touch, such as `[1, 3]` and `[3, 5]`, share the point 3 and must be merged into `[1, 5]`. The intervals `[1, 2]` and `[3, 4]` share no point and stay separate. - Merging is transitive: if A overlaps B and B overlaps C, all three become one interval, even when A and C do not overlap. - Return the merged intervals as a list of `[start, end]` pairs sorted by `start` in ascending order. No two returned intervals share a point, and together they cover exactly the points covered by the input. ### Constraints - `1 <= len(intervals) <= 10^5` - `-10^9 <= start <= end <= 10^9` for every interval - Every input and output value lies within `[-10^9, 10^9]`, so no value exceeds 2^31-1 and 32-bit integers suffice in every language. ### Examples **Example 1** ```text Input: intervals = [[8, 10], [1, 4], [3, 6], [12, 12]] Output: [[1, 6], [8, 10], [12, 12]] ``` `[1, 4]` and `[3, 6]` overlap on 3 to 4 and become `[1, 6]`. `[8, 10]` and the single point `[12, 12]` overlap nothing. **Example 2** ```text Input: intervals = [[1, 3], [3, 5], [6, 7]] Output: [[1, 5], [6, 7]] ``` `[1, 3]` and `[3, 5]` touch at 3, so they merge. `[1, 5]` and `[6, 7]` share no point.

Constraints

  • 1 <= len(intervals) <= 10^5
  • -10^9 <= start <= end <= 10^9 for every interval [start, end]
  • Every input and output value fits in a signed 32-bit integer (no value exceeds 2^31-1)

Examples

Input: ([[8, 10], [1, 4], [3, 6], [12, 12]],)

Expected Output: [[1, 6], [8, 10], [12, 12]]

Explanation: Source Example 1: [1, 4] and [3, 6] overlap; [8, 10] and the point [12, 12] stay separate; input is unsorted.

Input: ([[1, 3], [3, 5], [6, 7]],)

Expected Output: [[1, 5], [6, 7]]

Explanation: Source Example 2: touching endpoints at 3 merge; 5 and 6 share no point.

Hints

  1. Overlap means sharing at least one point: intervals that meet at a single endpoint overlap, while [1, 2] and [3, 4] do not.
  2. Merging is transitive, so one interval can connect two others that never overlap each other directly.
  3. An interval nested inside another can end before the outer one does; the merged result must still reach the outer interval's end.

Loading coding console...

Show the approach

Approach

Sort a copy of the intervals by (start, end), then sweep once while keeping the last merged block. If the next interval's start is at most the block's end, the two share a point (touching endpoints count because the intervals are closed), so the block's end becomes the maximum of the two ends. Taking the maximum rather than the newer end stops a nested interval that ends earlier from shrinking the block. Otherwise the next interval starts a new block. Invariant: after the first k sorted intervals are processed, the output is the start-sorted, pairwise disjoint union of exactly those k intervals, and the last block's end is the largest end in its group. Correctness: when the next start exceeds the block's end, every interval already in the block ends at or before that end, and every remaining interval starts at or after the next start, so no remaining interval can share a point with the block and the block is final. Transitive chains merge because each extension raises the end that later starts are compared against, and the output is sorted by start because blocks are emitted in sorted start order. Edge cases: a single interval is returned as-is; single points [x, x], duplicates and identical starts are handled by the same rule; endpoints at -10^9 and 10^9 fit in 32 bits, and the Java comparator uses Integer.compare so comparing 10^9 with -10^9 cannot overflow. Every reference copies the input before sorting, so the caller's list is not reordered.

Time complexity:
O(n log n)
Space complexity:
O(n)