Given an integer array nums
and an integer k
, return the k
th largest element in the array. Note that it is the k
th largest element in the sorted order, not the k
th distinct element.
For example:
nums = [3,2,1,5,6,4], k = 2
should return 5
nums = [3,2,3,1,2,4,5,5,6], k = 4
should return 4
Can you solve it without sorting?
Constraints:
1 <= k <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
Explain the time and space complexity of your solution. Consider edge cases like k=1, k=nums.length, and duplicate elements.
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To find the Kth largest element, we can sort all the elements from largest to smallest. Then we just pick the element that's in the Kth position. This method doesn't require any clever tricks, just sorting.
Here's how the algorithm would work step-by-step:
def find_kth_largest(numbers, k_value):
# Sort the array in descending order.
sorted_numbers = sorted(numbers, reverse=True)
# K_value is 1-indexed, adjust to 0-indexed.
kth_largest_index = k_value - 1
# Access the element at the adjusted index.
return sorted_numbers[kth_largest_index]
To efficiently find the kth largest element, we use a process similar to sorting, but we only focus on the part of the data that helps us find the answer. We repeatedly divide the data into smaller portions, eliminating the portions that cannot possibly contain the kth largest element.
Here's how the algorithm would work step-by-step:
def find_kth_largest(nums, k):
def partition(numbers, left_index, right_index):
pivot_element = numbers[right_index]
i = left_index
for j in range(left_index, right_index):
if numbers[j] >= pivot_element:
numbers[i], numbers[j] = numbers[j], numbers[i]
i += 1
numbers[i], numbers[right_index] = numbers[right_index], numbers[i]
return i
def quickselect(numbers, left_index, right_index, k_index):
# Only one element, return it.
if left_index == right_index:
return numbers[left_index]
pivot_index = partition(numbers, left_index, right_index)
# Found the kth largest element.
if k_index == pivot_index:
return numbers[k_index]
# Search left subarray.
elif k_index < pivot_index:
return quickselect(numbers, left_index, pivot_index - 1, k_index)
# Search right subarray.
else:
return quickselect(numbers, pivot_index + 1, right_index, k_index)
array_length = len(nums)
# Convert k to index from start
k_index_from_start = k -1
return quickselect(nums, 0, array_length - 1, array_length - k_index_from_start - 1)
Case | How to Handle |
---|---|
Empty array | Return null or throw an exception as there is no kth largest element in an empty array. |
k is less than or equal to 0 | Throw an exception or return null as k must be a positive integer to represent the kth largest. |
k is greater than the array length | Throw an exception or return null as the kth largest element cannot exist if k exceeds the array size. |
Array contains duplicate numbers | The sorting or heap-based solutions handle duplicates correctly as they consider the order, not distinctness. |
Array contains negative numbers | The comparison operations in sorting or heap-based approaches work correctly with negative numbers. |
Array contains all identical numbers | The sorting or heap-based solutions will still identify the correct kth largest element (which will be the repeated value). |
Large array size approaching memory limits | Consider using an in-place partitioning algorithm like quickselect to minimize memory usage. |
Integer overflow during calculations (if applicable) | Use appropriate data types (e.g., long) to prevent integer overflow during calculations, if any are performed. |