Smallest Range Covering Elements from K Lists
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.
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.
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.
nums: a list of k sorted lists of integers.
The smallest range, as two numbers [a, b].
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.
The value 1 is in every list, so the range [1, 1] has width 0.
[1, 2] and [5, 6] both have width 1. They tie, so the one with the smaller start, [1, 2], is the answer.
- • 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
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 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.
Does the start of the answer have to be one of the numbers in the lists?
- 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.
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.
Suppose the range starts at the smallest number I currently hold. If I move a different list forward, can the range get narrower?
- 6.
When one list runs out of numbers, can any range I have not checked yet still cover that list?
Brute force approach
Better approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | For each value lo, binary search every list for its first value ≥ lo; keep the narrowest range | O(N · k log n) | O(1) |
| Better | Merge every value onto one sorted line, then slide a window that must hold a value from every list | O(N log N) | O(N) |
| Optimal | Keep one value per list in a min-heap and track the largest; the range is [heap top, largest] | O(N log k) | O(k) |
Why does this belong to this pattern?
- “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.
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.
Don't make this mistake
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.
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.
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].
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like K-way Merge translate into production architectures and low-level memory mechanics.
Foundations: Object-Oriented Principles in C++23
Class invariants, pure virtual interfaces, and RAII smart pointers.
Food Delivery System (Zomato Architecture)
Real-world machine coding application of algorithms and design patterns.
Pointers vs References Deep Dive
Pointer arithmetic and memory layout under the hood.
Virtual Method Table (vtable) & Memory Layout
Polymorphism, vptr overhead, and multiple inheritance in memory.