2Brute2Best
🔥0

Smallest Range Covering Elements from K Lists

Hard·LeetCode #632Interview-Level
LeetCode
30-Second Mental ModelK-way Merge — Smallest range (min-heap with one value per list, plus curMax)
Complexity:O(N · k log n)→O(N log k)
Key Insight

Keep exactly one value from each list in a min-heap, and track curMax, the largest value in the heap. The heap top is the smallest, so the range is [heap top, curMax]. Only the smallest value can start a better range, so remove it and bring in the next value from the same list, updating curMax. Stop when a list runs out.

Core Validity Invariant

The range [heap top, curMax] is valid because the heap holds exactly one value from every list, so every list has a value between the smallest and the largest.

01

Problem

You get k lists of integers. Every list is sorted from smallest to largest.

Find the smallest range [a, b] such that every list has at least one number between a and b, with both ends included.

A range is smaller when its width b − a is smaller. If two ranges have the same width, the one with the smaller start a wins.

Input

nums: a list of k sorted lists of integers.

Output

The smallest range, as two numbers [a, b].

Example 1
Input: nums = [[4, 10, 15, 24, 26], [0, 9, 12, 20], [5, 18, 22, 30]]
Output: [20, 24]

The range holds 24 from list 0, 20 from list 1 and 22 from list 2. Its width is 4, and no other range that covers all three lists is narrower.

Example 2
Input: nums = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Output: [1, 1]

The value 1 is in every list, so the range [1, 1] has width 0.

Example 3
Input: nums = [[1, 5], [2, 6]]
Output: [1, 2]

[1, 2] and [5, 6] both have width 1. They tie, so the one with the smaller start, [1, 2], is the answer.

Constraints
  • • nums.length == k
  • • 1 ≤ k ≤ 3500
  • • 1 ≤ nums[i].length ≤ 50
  • • −10^5 ≤ nums[i][j] ≤ 10^5
  • • nums[i] is sorted in non-decreasing order
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    The range must contain a number from every list. If I fix the start of the range, what is the least the range has to reach in each list?

  2. 2.

    Does the start of the answer have to be one of the numbers in the lists?

  3. 3.

    If I put all the numbers on one sorted line, which parts of that line can count as a range that touches every list?

  4. 4.

    If I keep only one number from each list at a time, how do I find the smallest of them fast? What happens to the others?

  5. 5.

    Suppose the range starts at the smallest number I currently hold. If I move a different list forward, can the range get narrower?

  6. 6.

    When one list runs out of numbers, can any range I have not checked yet still cover that list?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFor each value lo, binary search every list for its first value ≥ lo; keep the narrowest rangeO(N · k log n)O(1)
BetterMerge every value onto one sorted line, then slide a window that must hold a value from every listO(N log N)O(N)
OptimalKeep one value per list in a min-heap and track the largest; the range is [heap top, largest]O(N log k)O(k)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “smallest range”A start and an end judged by width: the minimum-width window that touches many lists.
  • “at least one number from every list”Every list must be represented, so keep one candidate per list at a time.
  • “sorted lists”Each list's next value is its next bigger one, so each candidate can move forward on its own.
K sorted lists+range must touch every list+one candidate per list in a min-heap + running max→K-way Merge — Smallest range (min-heap with one value per list, plus curMax)

Merge K Sorted Lists also keeps a heap of one value per list, but it has to output every value, so it runs until all lists are empty. This question asks for a range, so the heap keeps one value per list, the end is a running curMax, and the answer is [heap top, curMax]. The stop rule is different too: this question stops as soon as one list runs out, because no later range can touch that list.

10

Don't make this mistake

Forgetting to update curMax when a value is pushed
✗ heap.push({nums[row][col + 1], row, col + 1}); // curMax is not touched
✓ heap.push({nums[row][col + 1], row, col + 1}); curMax = max(curMax, nums[row][col + 1]);

On the dry run, curMax stays 5 forever. After the first pop (0 from list 1), the code records [4, 5], which has no value from list 1 at all, because its next value is 9. The final answer comes out as [20, 5], a range that ends before it starts.

Pattern confusion: running until every list is empty
✗ while (!heap.empty()) { auto [v, row, col] = heap.top(); heap.pop(); if (col + 1 < (int)nums[row].size()) { heap.push({nums[row][col + 1], row, col + 1}); curMax = max(curMax, nums[row][col + 1]); } }
✓ if (col + 1 == (int)nums[row].size()) break; // a list is used up: stop here

Merge K Sorted Lists keeps going until every list is empty, because it has to output every value. This problem needs a value from every list, so once one list is used up, no later range can cover it. On the dry run, popping 20 (the last value of list 1) leaves only 22 and 24 in the heap, and the wrong code records [22, 24], which has no value from list 1. It keeps going and ends at [30, 30], which has no value from list 0.

Using <= in the width check
✗ if (width <= bestWidth) { bestWidth = width; best = {lo, curMax}; }
✓ if (width < bestWidth) { bestWidth = width; best = {lo, curMax}; }

On [[1, 5], [2, 6]], the range [1, 2] has width 1, and so does [5, 6]. The heap top only goes up, so [5, 6] is found later and has the larger start. With <= it replaces [1, 2], and the code returns [5, 6]. The tie rule keeps [1, 2].

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like K-way Merge translate into production architectures and low-level memory mechanics.