Kth Largest Element in an Array – Solution & Complexity
Solution Walkthrough
Step 1: What "kth largest" means
- Sort
numsfrom largest to smallest and return the value at positionk(1-based). - For
[3,2,1,5,6,4]the descending order is6, 5, 4, 3, 2, 1, so withk = 2the answer is5. - The simplest correct solution is exactly that: sort and index. It costs O(n log n) time, but it orders all
nvalues when we only care about the topk.
- Sort
Step 2: Keep only the k largest values seen so far
- Scan the array once and keep a small set of candidates: the
klargest values seen so far. - When a new value arrives, it joins the candidates. If that makes
k + 1candidates, the smallest one can never be the answer any more — at leastkvalues are already larger than or equal to it — so drop it. - After the last value, the candidates are exactly the
klargest values in the array, and the smallest candidate is the kth largest. - So we need a structure that cheaply answers "what is the smallest candidate?" and removes it. That is a min-heap of size at most
k.
- Scan the array once and keep a small set of candidates: the
Step 3: Why a min-heap (not a max-heap)
- Invariant: after processing each value, the heap holds the
klargest values seen so far (or all of them, if fewer thankhave been seen). - A min-heap keeps its smallest element at the root, so the candidate to evict is always
heap[0]. Push and pop each cost O(log k) because the heap never grows pastk + 1elements. - At the end the root is the smallest of the
klargest values, i.e. the kth largest. Read it without popping. - A max-heap would put the largest value on top, which is the wrong value to evict. You could instead heapify all
nvalues into a max-heap and popk - 1times, but that keeps O(n) values in memory instead of O(k).
- Invariant: after processing each value, the heap holds the
Step 4: Trace: nums = [3,2,1,5,6,4], k = 2
Each step pushes the value, then pops the root if the heap holds more than
k = 2values. The candidates column lists the retained values sorted for readability; it is not the heap's internal array layout.Value After push (sorted) Popped root Candidates after step (sorted) Root 3 {3}— {3}3 2 {2, 3}— {2, 3}2 1 {1, 2, 3}1 {2, 3}2 5 {2, 3, 5}2 {3, 5}3 6 {3, 5, 6}3 {5, 6}5 4 {4, 5, 6}4 {5, 6}5 The final candidates
{5, 6}are the two largest values, and the root5is the answer.Step 5: Duplicates count toward the rank
- Equal values occupy separate positions. For
nums = [3,2,3,1,2,4,5,5,6]the descending order is6, 5, 5, 4, 3, 3, 2, 2, 1. - With
k = 4the answer is4. If you deduplicated first, the distinct values6, 5, 4, 3would give3— a different (wrong) answer. - The heap handles this naturally: both
5s are pushed as separate entries, and the final candidates are{4, 5, 5, 6}with root4. Do not use a set for the candidates. - Other edge cases:
k = 1returns the maximum,k = nreturns the minimum, negative values and all-equal arrays (e.g.[5,5,5],k = 2→5) need no special handling.
- Equal values occupy separate positions. For
Step 6: Final Solution and Complexity
Every language below uses a size-k min-heap: push each value, pop the root when the size exceeds
k, and return the root at the end. Python usesheapq, JavaPriorityQueue, C++priority_queuewithstd::greater, RustBinaryHeap<Reverse<i32>>, and JavaScript, Go and Ruby a small hand-written binary min-heap.Approach Time Extra space Sort, then index O(n log n) O(n) or O(1) depending on the sort Size-k min-heap (this solution) O(n log k) O(k) Quickselect expected O(n), worst case O(n²) O(1) with an in-place partition - The heap is a good default: predictable O(n log k) time, works on a stream, and only O(k) memory.
- Quickselect partitions around a pivot and recurses into one side only. With random pivots it runs in expected linear time, but consistently bad pivots degrade it to O(n²).