Kth Largest Element in an Array 🧠
LeetCode Link: Kth Largest Element in an Array
Difficulty: Medium
Problem Explanation 📝
Problem: LeetCode 215 - Kth Largest Element in an Array
Description:
Given an integer array nums
and an integer k
, return the kth largest element in the array.
Note that it is the kth largest element in the sorted order, not the kth distinct element.
Intuition: The code uses the Quickselect algorithm to find the kth largest element in the array efficiently. Quickselect is a variation of the QuickSort algorithm and works by partitioning the array based on a chosen pivot element. Instead of sorting both sides of the partition like in QuickSort, Quickselect only focuses on the side of the partition that contains the desired kth largest element.
Approach:
- The code implements the Quickselect algorithm to efficiently find the kth largest element.
- Quickselect is a variation of the QuickSort algorithm that focuses on the desired kth largest element during partitioning.
- The
quickselect
function is a helper function that takes the input arraynums
, start indexl
, end indexr
, and the value ofk
as parameters.
- It returns the kth largest element in the array by recursively partitioning the array.
- Base case:
- If the start index
l
is greater than or equal to the end indexr
, it means we have found the kth largest element, so we return the element at indexl
.
- Partitioning:
- The code chooses the pivot element as
nums[l + r >> 1]
, which is the element at the middle index betweenl
andr
. - It initializes two pointers,
i
andj
, wherei
starts froml - 1
andj
starts fromr + 1
. - The code enters a loop where it increments
i
until it finds an element greater than the pivot and decrementsj
until it finds an element smaller than the pivot. - If
i
is less thanj
, it means there are elements on the wrong side of the partition, so it swapsnums[i]
andnums[j]
.
- After the loop:
- The code calculates the size of the smaller partition as
sl = j - l + 1
.
- Recursion:
- If
k
is less than or equal tosl
, it means the desired element is in the smaller partition, so it recursively callsquickselect
on that partition. - If
k
is greater thansl
, it means the desired element is in the larger partition, so it recursively callsquickselect
on that partition, adjustingk
by subtractingsl
.
- The
findKthLargest
function is the main function that takes the input arraynums
and integerk
as parameters.
- It disables synchronization between C and C++ standard streams for faster I/O.
- It returns the result of the
quickselect
function called withnums
, 0 as the start index,nums.size() - 1
as the end index, andk
.
⌛ Time Complexity:
- On average, the Quickselect algorithm has a time complexity of O(n), where n is the number of elements in the input array.
- However, in the worst case, Quickselect can have a time complexity of O(n^2) if the pivot selection is unbalanced.
- Overall, the average time complexity of Quickselect is O(n), making it an efficient algorithm for finding the kth largest element.
💾 Space Complexity:
- The space complexity is O(log n) for the recursive call stack of the
quickselect
function, where n is the number of elements in the input array. - In addition to the input array, the algorithm uses a constant amount of extra space.
- Therefore, the overall space complexity is O(log n).
Solutions 💡
Cpp 💻
class Solution {
public:
int quickselect(vector<int> &nums, int left, int right, int k) {
// Base case: if the left and right indices are the same, return the element at that index
if (left >= right) {
return nums[left];
}
// Choose a pivot element
int pivot = nums[left + (right - left) / 2];
// Initialize two pointers, one from the left and one from the right
int i = left - 1;
int j = right + 1;
// Partition the array around the pivot
while (i < j) {
// Find the first element greater than the pivot from the left side
while (nums[++i] > pivot);
// Find the first element smaller than the pivot from the right side
while (nums[--j] < pivot);
// Swap the elements if the pointers haven't crossed each other
if (i < j) {
swap(nums[i], nums[j]);
}
}
// Calculate the size of the smaller partition
int smallerPartitionSize = j - left + 1;
// If the desired element is in the smaller partition, recursively call quickselect on that partition
if (k <= smallerPartitionSize) {
return quickselect(nums, left, j, k);
}
// If the desired element is in the larger partition, recursively call quickselect on that partition
return quickselect(nums, j + 1, right, k - smallerPartitionSize);
}
int findKthLargest(vector<int> &nums, int k) {
// Disable synchronization between C and C++ standard streams for faster I/O
cin.tie(0);
ios::sync_with_stdio(false);
// Call the quickselect algorithm to find the kth largest element
return quickselect(nums, 0, nums.size() - 1, k);
}
};
Python 🐍
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
min_heap = []
for num in nums:
heapq.heappush(min_heap, num)
if len(min_heap) > k:
heapq.heappop(min_heap)
return min_heap[0]