Kth Largest Element in an Array
Given an array of integers, nums, and a value k, return the kth largest element.
Example(s)
Example 1:
Input: nums = [1, 2, 3], k = 1
Output: 3
Explanation:
Sorted: [1, 2, 3]
1st largest = 3
Example 2:
Input: nums = [9, 2, 1, 7, 3, 2], k = 5
Output: 2
Explanation:
Sorted: [1, 2, 2, 3, 7, 9]
5th largest = 2
Example 3:
Input: nums = [3, 2, 1, 5, 6, 4], k = 2
Output: 5
Explanation:
Sorted: [1, 2, 3, 4, 5, 6]
2nd largest = 5
Solution
There are multiple approaches:
- Sorting: Sort array and return kth from end - O(n log n)
- Min Heap: Maintain heap of size k - O(n log k)
- Quickselect: Partition-based selection - O(n) average
- JavaScript Solution - Sorting
- Python Solution - Sorting
JavaScript Solution - Sorting
/**
* Find kth largest element using sorting
* @param {number[]} nums - Input array
* @param {number} k - Kth largest position
* @return {number} - Kth largest element
*/
function findKthLargest(nums, k) {
// Sort in descending order
nums.sort((a, b) => b - a);
// Return kth element (0-indexed, so k-1)
return nums[k - 1];
}
// Test cases
console.log('Example 1:', findKthLargest([1, 2, 3], 1));
// 3
console.log('Example 2:', findKthLargest([9, 2, 1, 7, 3, 2], 5));
// 2
console.log('Example 3:', findKthLargest([3, 2, 1, 5, 6, 4], 2));
// 5Output:
Click "Run Code" to execute the code and see the results.
Python Solution - Sorting
from typing import List
def find_kth_largest(nums: List[int], k: int) -> int:
"""
Find kth largest element using sorting
Args:
nums: Input array
k: Kth largest position
Returns:
int: Kth largest element
"""
# Sort in descending order
nums.sort(reverse=True)
# Return kth element (0-indexed, so k-1)
return nums[k - 1]
# Test cases
print('Example 1:', find_kth_largest([1, 2, 3], 1))
# 3
print('Example 2:', find_kth_largest([9, 2, 1, 7, 3, 2], 5))
# 2
print('Example 3:', find_kth_largest([3, 2, 1, 5, 6, 4], 2))
# 5Loading Python runtime...
Output:
Click "Run Code" to execute the code and see the results.
Alternative Solution (Min Heap)
Here's a more efficient approach using a min heap:
- JavaScript Min Heap
- Python Min Heap
/**
* Min heap approach - O(n log k) time, O(k) space
*/
function findKthLargestHeap(nums, k) {
// Min heap of size k
const heap = [];
for (const num of nums) {
if (heap.length < k) {
heap.push(num);
heapifyUp(heap, heap.length - 1);
} else if (num > heap[0]) {
// Replace smallest element
heap[0] = num;
heapifyDown(heap, 0);
}
}
return heap[0]; // Root is kth largest
}
// Min heap helpers
function heapifyUp(heap, index) {
while (index > 0) {
const parent = Math.floor((index - 1) / 2);
if (heap[parent] <= heap[index]) break;
[heap[parent], heap[index]] = [heap[index], heap[parent]];
index = parent;
}
}
function heapifyDown(heap, index) {
while (true) {
let smallest = index;
const left = 2 * index + 1;
const right = 2 * index + 2;
if (left < heap.length && heap[left] < heap[smallest]) {
smallest = left;
}
if (right < heap.length && heap[right] < heap[smallest]) {
smallest = right;
}
if (smallest === index) break;
[heap[index], heap[smallest]] = [heap[smallest], heap[index]];
index = smallest;
}
}
import heapq
def find_kth_largest_heap(nums: List[int], k: int) -> int:
"""
Min heap approach - O(n log k) time, O(k) space
"""
# Min heap of size k
heap = []
for num in nums:
if len(heap) < k:
heapq.heappush(heap, num)
elif num > heap[0]:
# Replace smallest element
heapq.heapreplace(heap, num)
return heap[0] # Root is kth largest
Alternative Solution (Quickselect)
Here's the optimal average-case solution using quickselect:
- JavaScript Quickselect
- Python Quickselect
/**
* Quickselect approach - O(n) average, O(n²) worst case
*/
function findKthLargestQuickselect(nums, k) {
// Convert to 0-indexed: kth largest = (n-k)th smallest
const targetIndex = nums.length - k;
function quickselect(left, right, targetIndex) {
if (left === right) {
return nums[left];
}
const pivotIndex = partition(left, right);
if (pivotIndex === targetIndex) {
return nums[pivotIndex];
} else if (pivotIndex < targetIndex) {
return quickselect(pivotIndex + 1, right, targetIndex);
} else {
return quickselect(left, pivotIndex - 1, targetIndex);
}
}
function partition(left, right) {
const pivot = nums[right];
let i = left;
for (let j = left; j < right; j++) {
if (nums[j] <= pivot) {
[nums[i], nums[j]] = [nums[j], nums[i]];
i++;
}
}
[nums[i], nums[right]] = [nums[right], nums[i]];
return i;
}
return quickselect(0, nums.length - 1, targetIndex);
}
def find_kth_largest_quickselect(nums: List[int], k: int) -> int:
"""
Quickselect approach - O(n) average, O(n²) worst case
"""
# Convert to 0-indexed: kth largest = (n-k)th smallest
target_index = len(nums) - k
def quickselect(left: int, right: int, target_index: int) -> int:
if left == right:
return nums[left]
pivot_index = partition(left, right)
if pivot_index == target_index:
return nums[pivot_index]
elif pivot_index < target_index:
return quickselect(pivot_index + 1, right, target_index)
else:
return quickselect(left, pivot_index - 1, target_index)
def partition(left: int, right: int) -> int:
pivot = nums[right]
i = left
for j in range(left, right):
if nums[j] <= pivot:
nums[i], nums[j] = nums[j], nums[i]
i += 1
nums[i], nums[right] = nums[right], nums[i]
return i
return quickselect(0, len(nums) - 1, target_index)
Complexity
- Time Complexity:
- Sorting: O(n log n) - Sort the entire array
- Min Heap: O(n log k) - Process n elements, heap operations are O(log k)
- Quickselect: O(n) average, O(n²) worst case
- Space Complexity:
- Sorting: O(1) or O(n) depending on sorting algorithm
- Min Heap: O(k) - Heap of size k
- Quickselect: O(1) - In-place partitioning
Approach
Sorting Approach:
- Sort array: Sort in descending order
- Return kth element: Return element at index k-1
Min Heap Approach:
- Maintain heap of size k: Keep k largest elements
- Min heap property: Root is the smallest of k largest
- Process elements: For each element, if larger than root, replace root
- Return root: Root is the kth largest
Quickselect Approach:
- Partition: Use pivot to partition array
- Recurse: Recursively search in the correct partition
- Target index: kth largest = (n-k)th smallest
- Average O(n): Each partition eliminates half on average
Key Insights
- Sorting is simple: Easy to implement, O(n log n)
- Min heap is efficient: O(n log k), better when k
<<n - Quickselect is optimal: O(n) average case
- Kth largest = (n-k)th smallest: Useful for quickselect
- Heap size k: Only need to track k largest elements
Step-by-Step Example
Let's trace through Example 1: nums = [1, 2, 3], k = 1
Sorting Approach:
Original: [1, 2, 3]
Sorted (descending): [3, 2, 1]
k = 1, so return index 0: 3
Min Heap Approach (k = 1):
Process 1: heap = [1]
Process 2: 2 > 1, replace: heap = [2]
Process 3: 3 > 2, replace: heap = [3]
Return heap[0] = 3
Quickselect Approach:
targetIndex = 3 - 1 = 2 (2nd smallest = 1st largest)
Partition [1, 2, 3] with pivot 3:
Elements <= 3: [1, 2, 3]
pivotIndex = 2
pivotIndex == targetIndex? Yes
Return nums[2] = 3
Visual Representation
Example 1: nums = [1, 2, 3], k = 1
Sorted (descending): [3, 2, 1]
↑
1st largest = 3
Example 2: nums = [9, 2, 1, 7, 3, 2], k = 5
Sorted (descending): [9, 7, 3, 2, 2, 1]
1 2 3 4 5 6
↑
5th largest = 2
Edge Cases
- k = 1: Return maximum element
- k = n: Return minimum element
- k = n/2: Return median
- All same elements: Returns that element
- Duplicates: Works correctly (kth largest, not kth distinct)
Important Notes
- Kth largest: Not kth distinct largest
- 1-indexed: k = 1 means largest, k = 2 means second largest
- Duplicates count: [2, 2, 1] with k=2 returns 2
- Sorting modifies array: May need to copy if original needed
- Heap is efficient: Better when k is small
Comparison of Approaches
| Approach | Time | Space | Best For |
|---|---|---|---|
| Sorting | O(n log n) | O(1) | Simple, small arrays |
| Min Heap | O(n log k) | O(k) | When k << n |
| Quickselect | O(n) avg | O(1) | When k ≈ n/2 |
Related Problems
- Kth Smallest Element: Similar problem
- Top K Frequent Elements: Different problem
- Find Median: Special case (k = n/2)
- K Closest Points: Different selection problem
Takeaways
- Sorting is simplest but O(n log n)
- Min heap is efficient when k is small
- Quickselect provides optimal average case
- Kth largest = (n-k)th smallest for quickselect
- Choose based on constraints and k value