An integer array nums and a positive integer k are given. Arrange every array occurrence by value from largest to smallest and consider every duplicate occurrence as a separate position.
Return the value occupying position k in the descending order.
Example 1
Input: nums = [3, 2, 3, 1, 2, 4, 5, 5, 6], k = 4
Output: 4
Explanation: Descending order becomes [6, 5, 5, 4, 3, 3, 2, 2, 1]. Position 4 contains 4, and both occurrences of 5 occupy separate positions.
Example 2
Input: nums = [7], k = 1
Output: 7
Explanation: A single-element array has the same value as the largest and smallest ranked element.
Brute Force Approach
Sorting the complete array makes the k-th largest element easy to locate. After sorting in ascending order, the k-th largest value appears at index n - k.
This approach is simple and provides a clear baseline, but it sorts all elements even though only one value is required.
Algorithm
Copy
numsintosortedNumsso the original array remains unchanged.Sort
sortedNumsin ascending order so every element gets its correct sorted position.Store the array size in
nbecause the k-th largest position depends on the total number of elements.Calculate the required index as
n - k, because the k-th largest element appears at that position in ascending order.Return
sortedNums[n - k]as the k-th largest element.
Dry Run
k-th-largest-element-in-an-array-brute-force-heading-brute-approach-final.png
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: // Finds the kth largest value by sorting a copy. int findKthLargest(vector<int>& nums, int k) { // Copy the array to preserve the original order. vector<int> sortedNums = nums; // Sort the copied values in ascending order. sort(sortedNums.begin(), sortedNums.end()); int n = sortedNums.size(); // Convert the descending rank to an ascending index. int targetIndex = n - k; // Read the value stored at the required rank. return sortedNums[targetIndex]; }};// Driver codeint main() { vector<int> nums = {3, 2, 1, 5, 6, 4}; int k = 2; Solution obj; cout << obj.findKthLargest(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N log N), where N is the number of elements in the array, because sorting all N copied values determines their complete order.
Space Complexity: O(N), because the copied array stores N values apart from language-specific sorting overhead.
Better Approach
Sorting the whole array does more work than needed because only the k largest elements matter. A min-heap of size k keeps only these useful candidates, with the smallest among them always available at the root.
Whenever the heap grows beyond k, remove its smallest value because it cannot remain among the current top k elements. After processing the complete array, the heap contains exactly the k largest occurrences, so its root is the k-th largest element.
Algorithm
Create an empty min-heap named
minHeapso the smallest retained candidate always stays at the root.Traverse every value in
numsso each occurrence gets a chance to enter the topk.Push the current value into
minHeapbecause it may belong among theklargest elements.If the heap size becomes greater than
k, remove the root because the smallest candidate is no longer needed.Keep duplicate values as separate heap entries because each occurrence has its own rank in sorted order.
After processing all elements, return the heap root because it is the smallest value among the
klargest elements, making it the k-th largest.
Dry Run
Kth largest element in array better
Solution
#include <bits/stdc++.h>using namespace std;class Solution {public: // Finds the kth largest value with a size-k heap. int findKthLargest(vector<int>& nums, int k) { priority_queue<int, vector<int>, greater<int>> minHeap; // Process every value as a ranked candidate. for (int value : nums) { // Add the current value to the candidate heap. minHeap.push(value); // An overflow contains one unnecessary value. if (minHeap.size() > k) { // Remove the smallest candidate after overflow. minHeap.pop(); } } // The root is smallest among the top k values. return minHeap.top(); }};// Driver codeint main() { vector<int> nums = {3, 2, 3, 1, 2, 4, 5, 5, 6}; int k = 4; Solution obj; cout << obj.findKthLargest(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N log k), where N is the number of elements in the array, because every element is inserted into a heap containing at most k + 1 elements.
Space Complexity: O(k), because the min-heap stores at most k candidate elements.
Optimal Approach
Quickselect avoids fully sorting the array because only the position of the k-th largest element matters. Convert it to the ascending target index n - k, then repeatedly partition only the part of the array that can still contain this index.
A three-way partition separates values into smaller, equal, and greater groups around a pivot. This handles duplicate values efficiently because all values equal to the pivot are processed together. Random pivot selection helps avoid consistently unbalanced partitions.
Algorithm
Convert the k-th largest rank into target index
n - k, because Quickselect works naturally with ascending positions.Set
left = 0andright = n - 1to represent the active range containing the target.Choose a random pivot from the active range to reduce the chance of repeatedly poor partitions.
Use three pointers:
smallermarks where values smaller than the pivot should go.currentscans the active range.greatermarks where values greater than the pivot should go.
While
current <= greater:If the current value is smaller than the pivot, move it toward
smallerand advance both pointers.If the current value is greater than the pivot, move it toward
greaterand decreasegreater.If the current value equals the pivot, advance
currentso equal values remain in the middle.
After partitioning:
If the target lies inside the equal region, return the pivot because the required rank has been found.
If the target lies to the left, continue only with the left part.
Otherwise, continue only with the right part.
Repeat until the target value is found.
Dry Run
kth largest array optimal
Solution
#include <bits/stdc++.h>using namespace std;class Solution {private: // Swaps values stored at two array positions. void swapValues(vector<int>& nums, int first, int second) { int temporary = nums[first]; nums[first] = nums[second]; nums[second] = temporary; } // Splits a range into smaller, equal, and larger. pair<int, int> partition(vector<int>& nums, int left, int right) { // Choose a pivot from the active range. int pivotIndex = left + rand() % (right - left + 1); int pivotValue = nums[pivotIndex]; int smaller = left; int current = left; int greater = right; // Classify every value in the active range. while (current <= greater) { // Smaller values grow the left region. if (nums[current] < pivotValue) { swapValues(nums, current, smaller); smaller++; current++; continue; } // Larger values grow the right region. if (nums[current] > pivotValue) { swapValues(nums, current, greater); greater--; continue; } // Equal values grow the middle region. current++; } return make_pair(smaller, greater); }public: // Finds the kth largest value with Quickselect. int findKthLargest(vector<int>& nums, int k) { int n = nums.size(); // Seed pivot choices before selection begins. srand(time(0)); // Convert the descending rank to an ascending index. int targetIndex = n - k; int left = 0; int right = n - 1; // Narrow search to the range containing the target. while (left <= right) { pair<int, int> equalRange = partition(nums, left, right); int equalStart = equalRange.first; int equalEnd = equalRange.second; // A target inside the equal band has the answer. if (targetIndex >= equalStart && targetIndex <= equalEnd) { return nums[targetIndex]; } // A left target discards the middle and right. if (targetIndex < equalStart) { right = equalStart - 1; } else { // A right target discards the middle and left. left = equalEnd + 1; } } // Valid inputs always locate a target value. return -1; }};// Driver codeint main() { vector<int> nums = {3, 2, 1, 5, 6, 4}; int k = 2; Solution obj; cout << obj.findKthLargest(nums, k) << endl; return 0;}Complexity Analysis
Time Complexity: O(N) on average, where N is the number of elements in the array, because each partition reduces the active search range. In the worst case, repeatedly choosing extreme pivots leads to O(N2) time.
Space Complexity: O(1), because in-place partitioning and iterative range updates use only a fixed number of variables.
Interview follow-up Questions
Yes. Every duplicate occurrence occupies a separate sorted-order position. For example, descending order [5, 5, 4] gives rank 2 to value 5.
Be the first to add a comment.