Kth Largest Element in a Stream
Keep a min-heap that holds only the k largest numbers seen so far. On each add, push the value, then pop the smallest if the heap has more than k items. Its top is the smallest of the k largest, which is the kth largest overall.
The heap always holds exactly the k largest numbers seen so far. That makes its top, the smallest of them, the kth largest in the whole stream.
Problem
Build a class KthLargest that keeps a stream of numbers and can tell you its kth largest value at any moment.
KthLargest(int k, vector<int>& nums)starts the stream with the numbers innums.int add(int val)addsvalto the stream and returns the kth largest number in the stream now.
"kth largest" means: sort the numbers from biggest to smallest and count down from the top. If a number appears twice, each copy counts as its own number.
The integer k, the starting list nums, and then a series of add(val) calls.
For each add call, the kth largest number after that value is added.
The stream starts as 8, 5, 4, 2, so the 3rd largest is 4. After add(3) the list is 8, 5, 4, 3, 2 and the 3rd is still 4. After add(5) it is 8, 5, 5, 4, 3, 2, so the 3rd is 5. add(10) gives 10, 8, 5, 5, 4, 3, 2, and the 3rd is 5 again. add(9) pushes it to 8, and add(4) leaves it at 8.
With k = 1 the answer is simply the largest number so far. After -3 it is -3. After -2 the largest is -2. Adding -7 does not change it.
- • 0 ≤ nums.length ≤ 10^4
- • 1 ≤ k ≤ nums.length + 1
- • −10^4 ≤ nums[i] ≤ 10^4
- • −10^4 ≤ val ≤ 10^4
- • At most 10^4 calls will be made to add
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
The answer is a rank, not a value. If the stream holds 8, 5, 5, 4, which number is the 3rd largest?
- 2.
If I kept every number and sorted on each add, how much work would one add cost?
- 3.
Suppose k numbers in the stream are already bigger than some value x. Can x ever be the kth largest after that?
- 4.
Which heap keeps the smallest item on top, and could that smallest item be the one I throw away?
- 5.
The question only asks about the kth largest. Do I really need to remember every number to answer it forever?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | Keep every number, sort the whole list on each add, read position k | O(N log N) | O(N) |
| Optimal | Keep only the k largest in a min-heap; the top is the kth largest | O(log k) | O(k) |
Why does this belong to this pattern?
- “kth largest”A rank counted from the top. The answer is the smallest of the k largest, so a size-k group is enough.
- “a stream, with add(val)”Numbers keep arriving. The answer must be ready after every add, without re-reading old numbers.
- “returns the kth largest after each add”Keep a size-k min-heap: one push and at most one pop per add.
The Kth Largest Element in an Array question asks for one answer over a fixed array. This question must answer after every add, so the heap has to stay correct as numbers arrive. The rule that makes it work is throw away the smallest as soon as there are k + 1 numbers. For the k smallest numbers, flip the heap to a max-heap; the same idea applies.
Don't make this mistake
A min-heap of everything has the overall smallest on top, not the kth largest. On the dry run, after the constructor, the heap holds {2, 4, 5, 8}, so the top is 2. The 3rd largest of 8, 5, 4, 2 is 4, but this version returns 2. After add(3), the heap is {2, 3, 4, 5, 8} and it still returns 2. The heap must be cut back to k.
A max-heap's top is the largest number. Popping when the size is above k then removes the biggest number and keeps the k smallest. On the dry run, the constructor leaves {2, 4, 5} in the max-heap, so the first answer would be 5 instead of 4.
Popping first removes the smallest of the k numbers before we know whether val is bigger. On add(3) with the heap {4, 5, 8}, the pop-first version removes 4, pushes 3, and returns 3. The correct answer is 4, because 3 is the smallest of the four candidates and must be the one dropped.
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 Heap — Top K translate into production architectures and low-level memory mechanics.