We have an array of integers and need to find the kth largest element in sorted order, counting by position rather than by distinct value. If the array were sorted in descending order, the answer is the element at position k from the top. Duplicates each count as a separate position.
For example, in [3,2,3,1,2,4,5,5,6], the sorted descending order is [6,5,5,4,3,3,2,2,1]. The 4th largest is 4, even though there are only 6 distinct values.
The problem also hints at solving it without sorting, which suggests there is a more efficient approach than the obvious O(n log n) sort. There are three standard approaches with different trade-offs: full sort, a size-k heap, and quickselect.
1 <= k <= nums.length <= 10^5 → n reaches 100,000, so a guaranteed O(n^2) approach is too slow. O(n log n) is safe, and O(n) average is achievable. Since k is always within bounds, there is no invalid-k case to handle.-10^4 <= nums[i] <= 10^4 → Values span only 20,001 distinct integers, which makes counting-based approaches viable as an alternative.Sort the entire array, then read off the answer by index. In an ascending sort, the kth largest element sits at index n - k: there are exactly k - 1 elements larger than it, all to its right. In a descending sort, it sits at index k - 1.
This is easy to code and easy to verify, and with n up to 10^5 an O(n log n) sort runs in a few milliseconds. It does more work than needed, since it orders every element when we only want one, but it establishes a correct baseline.
nums.length - k.The next approach avoids ordering the whole array by tracking only the k largest elements seen so far.
Maintain a collection of only the k largest elements seen so far. The smallest element in that collection is the kth largest overall, so once the whole array is processed, that minimum is the answer.
A min-heap of size k fits this exactly, because it gives O(1) access to its minimum and O(log k) insertion. Scan through the array adding each element to the heap. Whenever the heap grows beyond size k, remove the minimum. After all elements are processed, the heap holds the k largest values, and its root is the kth largest.
The invariant is: after processing the first i elements, the heap holds the largest min(i, k) of them. Adding the next element keeps the heap a superset of the true top set by at most one extra value, and removing the minimum discards a value that cannot be among the k largest (k larger or equal values already remain in the heap). The invariant is preserved, so after all n elements the heap holds the k largest of the array and its root is the kth largest.
The heap approach is O(n log k), which is efficient when k is small. The next approach reaches O(n) average time by partitioning the array and discarding the half that cannot contain the answer at each step.
Quickselect uses the same partition step as quicksort but recurses into only one side. After partitioning around a pivot, every element to the left is smaller and every element to the right is larger, so the pivot sits at its final sorted position. If that position is the target index n - k, the pivot is the answer. If the target is to the left, search the left partition; if to the right, search the right partition. The other side is discarded.
Using a three-way partition (Dutch National Flag) splits the range into < pivot, == pivot, and > pivot. This settles every copy of the pivot value in one pass, so arrays with many duplicates do not degrade into repeated partitions over equal elements.
On average each partition discards about half the remaining elements, giving O(n) + O(n/2) + O(n/4) + ... = O(2n) = O(n) average work, compared with O(n log n) to sort everything.
After a three-way partition, the indices [lo, hi] all hold the pivot value and are in their final sorted positions. If targetIndex falls in [lo, hi], every element at those indices equals the pivot, so the pivot value is the answer regardless of which exact index the target is. If targetIndex < lo, the answer lies among the smaller elements in [left, lo-1]; if targetIndex > hi, it lies among the larger elements in [hi+1, right]. Each step strictly shrinks the search range, so the loop terminates.
nums.length - k (the position of the kth largest in a sorted array).