LeetCode 215: Kth Largest Element in an Array - Optimal C++ Solution
Problem Statement
Given an integer array nums and an integer k, return the kth largest element in the array.
Example:
Input:
nums = [3,2,1,5,6,4], k = 2
Output:
5
Constraints:
1 <= k <= nums.length <= 10^4
-10^4 <= nums[i] <= 10^4
Optimal Approach: Min-Heap (Priority Queue)
Explanation:
- Use a Min-Heap of size
k: Store only the k largest elements.
- Iterate through
nums, pushing elements into the heap.
- If the heap size exceeds
k, pop the smallest element.
- The root of the heap is the
kth largest element.
C++ Implementation (LeetCode-Compatible)
#include <vector>
#include <queue>
using namespace std;
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> minHeap;
for (int num : nums) {
minHeap.push(num);
if (minHeap.size() > k) {
minHeap.pop();
}
}
return minHeap.top();
}
};
Step-by-Step Explanation
- Min-Heap of size
k ensures that the k largest elements are always retained.
- Push elements into heap and remove the smallest whenever size exceeds
k.
- The top element is the answer since it's the
kth largest.
Dry Run Example:
Input:
nums = [3,2,1,5,6,4], k = 2
Execution Steps:
| Step |
Heap Content |
| 1 |
[3] |
| 2 |
[2, 3] |
| 3 |
[1, 2, 3] (pop 1) → [2, 3] |
| 4 |
[2, 3, 5] (pop 2) → [3, 5] |
| 5 |
[3, 5, 6] (pop 3) → [5, 6] |
| 6 |
[4, 5, 6] (pop 4) → [5, 6] |
| Result |
5 |
Alternative Approaches & Why Not?
| Approach |
Time Complexity |
Space Complexity |
Why Not Optimal? |
| Sorting |
O(N log N) |
O(1) |
Sorting is unnecessary |
| Max-Heap (Priority Queue) |
O(N log k) |
O(N) |
Uses extra space |
| QuickSelect (Hoare's Algorithm) |
O(N) avg, O(N^2) worst |
O(1) |
Unstable worst-case |
QuickSelect (Alternative)
#include <vector>
using namespace std;
class Solution {
public:
int partition(vector<int>& nums, int left, int right) {
int pivot = nums[right];
int i = left;
for (int j = left; j < right; j++) {
if (nums[j] >= pivot) {
swap(nums[i], nums[j]);
i++;
}
}
swap(nums[i], nums[right]);
return i;
}
int quickSelect(vector<int>& nums, int left, int right, int k) {
if (left == right) return nums[left];
int pivotIndex = partition(nums, left, right);
if (pivotIndex == k) return nums[k];
else if (pivotIndex < k) return quickSelect(nums, pivotIndex + 1, right, k);
else return quickSelect(nums, left, pivotIndex - 1, k);
}
int findKthLargest(vector<int>& nums, int k) {
return quickSelect(nums, 0, nums.size() - 1, k - 1);
}
};
Why is QuickSelect Less Optimal?
- Average Case: O(N), but Worst Case: O(N²).
- Unstable Partitioning can degrade performance.
- In-Place Algorithm but requires careful implementation.
Best Solution & Why?
| Approach |
Time Complexity |
Space Complexity |
Best Choice? |
| Min-Heap (Priority Queue) |
O(N log k) |
O(k) |
✅ Best balance |
| Sorting |
O(N log N) |
O(1) |
❌ Slower than heap |
| QuickSelect |
O(N) avg, O(N²) worst |
O(1) |
❌ Unstable worst-case |
Why is Min-Heap Best?
- Consistent O(N log k) Performance ✅
- Efficient Memory Usage (O(k)) ✅
- Stable & Easy to Implement ✅
Conclusion
- Best Solution: Min-Heap (Priority Queue).
- Why? Efficient O(N log k) time, stable performance, and simple implementation.
- Alternative Solutions: Sorting (extra computation), QuickSelect (unstable worst case).
Practice More: