215. Kth Largest Element in an Array
Leetcode Divide and Conquer HeapFind the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
Note: You may assume k is always valid, 1 ≤ k ≤ array's length.
分析¶
这道题最简单的思路莫过于把输⼊的n个整数排序,排序之后位于最后⾯的第k个数就是最大的第k个数。时间复杂度是n\log(n),空间复杂度为O(1)。
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0 || k > nums.length)
throw new IllegalArgumentException();
Arrays.sort(nums);
return nums[nums.length - k];
}
另一个方法是利用优先级队列保存前K个最大的数。时间复杂度是O(n\log k),空间复杂度是O(k). 该方法适用于海量数据,参考LeetCode 703. Kth Largest Element in a Stream。
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0 || k > nums.length)
throw new IllegalArgumentException();
final PriorityQueue<Integer> pq = new PriorityQueue<>();
for (int num : nums) {
pq.offer(num);
if (pq.size() > k) pq.poll();
}
return pq.peek();
}
public int findKthLargest(int[] nums, int k) {
if (nums == null || nums.length == 0 || k > nums.length)
throw new IllegalArgumentException();
int lo = 0, hi = nums.length - 1;
// 要调整K,不然求的是最小第K个数
k = nums.length - k;
while (lo < hi) {
int j = partition(nums, lo, hi);
if (j < k) lo = j + 1;
else if (j > k) hi = j - 1;
else return nums[j];
}
return nums[k];
}
private int partition(int[] nums, int lo, int hi) {
int pivot = nums[lo];
int i = lo + 1, j = hi;
while (true) {
while (i < hi && nums[i] <= pivot) i++;
while (j > lo && nums[j] >= pivot) j--;
if (i >= j) break;
swap(nums, i, j);
}
swap(nums, lo, j);
return j;
}
private void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}