Last Updated: April 4, 2026
We need a data structure that can handle a growing collection of numbers and quickly answer "what is the kth largest element right now?" every time a new number arrives. The stream only grows (we never remove elements), and we need to return the answer after each insertion.
Here is the key insight: we don't need to track all elements or maintain a fully sorted list. We only care about the top k elements at any given time. If we can efficiently maintain just the k largest elements, the smallest among them is our answer.
1 <= k <= 10^4 → k can be fairly large, so we need an approach that handles this efficiently.0 <= nums.length <= 10^4 → The initial array can be empty, which means the first few add calls might not yet have k elements.10^4 calls to add → Combined with nums.length, we could see up to 20,000 total elements. Each add call needs to be fast.-10^4 <= val <= 10^4 → Values can be negative. Don't assume all elements are positive.The most straightforward approach: every time add is called, insert the new element into the list, sort the entire list, and return the kth largest element (which is at index n - k after sorting).
This is simple to implement and easy to reason about. You are just maintaining a sorted list and reading off the kth position from the end.
k.add(val) is called, append val to the list.list.size() - k (the kth largest from the end).add call, where n is the current size of the list. Sorting takes O(n log n), and we do this on every call.Sorting the entire list every time works, but we're doing far more work than necessary. We only need the kth largest, not a fully sorted list. What if we maintained just the k largest elements using a data structure that gives us the minimum in O(1)?
We only care about the k largest elements at any point. If an element is smaller than all of the current top k, it can never be the kth largest, so we can discard it.
A min-heap (priority queue) of size k is the perfect tool for this. The heap's root always holds the smallest element in the heap, which is exactly the kth largest element overall. When a new value arrives, we push it onto the heap and pop the minimum if the heap exceeds size k.
Think of it like a VIP section with exactly k seats. To get in, you need to be bigger than the smallest person currently seated. If you are, the smallest person leaves and you sit down. The bouncer (the heap root) is always the smallest person in VIP, which is the kth largest overall.
The min-heap of size k acts as a filter. At any point, the heap contains exactly the k largest elements from the stream seen so far. Because it's a min-heap, the root (smallest element in the heap) is the kth largest overall. When a new element arrives that is larger than the root, it displaces the current kth largest, and the new root becomes the answer.
nums into the heap.add(val) is called, push val onto the heap.add call. Each heap push/pop on a heap of size k takes O(log k).