Question

Find 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.

For example,
Given ​​​[3,2,1,5,6,4]​​ and k = 2, return 5.

Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.


本题难度Easy。有3种算法分别是: 排序、优先队列和快速排序

题意

题目说的是要第K大的元素,而不是第K大的数。

1、排序法

复杂度

时间 O(NlogN) 空间 O(1)

思路

排序后,倒数第K个就是答案。

代码

public class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length-k];
}
}

2、优先队列

复杂度

时间 O(NlogK) 空间 O(K)

思路

遍历数组时将数字加入优先队列(堆),一旦堆的大小大于k就将堆顶元素去除,确保堆的大小为k。遍历完后堆顶就是返回值。

优先队列就是最小堆,最小值在根节点。

代码

public class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> p = new PriorityQueue<Integer>();
for(int i = 0 ; i < nums.length; i++){
p.add(nums[i]);
if(p.size()>k) p.poll();
}
return p.poll();
}
}

3、快速排序

复杂度

时间 Avg O(N) Worst O(N^2) 空间 O(1)

思路

跟快速排序一个思路。先取一个枢纽值,将数组中小于枢纽值的放在左边,大于枢纽值的放在右边,最后把枢纽值放到分界点(具体请看​​被忽视的 partition 算法​​)。如果分界点后面有k-1个数,说明分界点的数就是第k个数;否则,如果分界点后的数大于k-1,则在右半边做同样的搜索;如果分界点后的数小于k-1,则在左半边做同样的搜索。

背景资料:​​被忽视的 partition 算法​​
实现快速排序的方法很多,最直观的就是用两个List,一个存放小于pivot,一个存放大于pivot,但是这样既低效又浪费空间,所以推荐使用partition算法。它的核心实际上就是双指针法:

(重点复习)[LeetCode]Kth Largest Element in an Array_快速排序

​begin​​​代表的是小于等于​​pivot​​​值的边界(不含​​begin​​​本身),end代表的是大于等于pivot的边界(不含​​end​​​本身),这样两指针逐渐往中间靠拢,最后​​begin==end​​​其位置就是​​pivot​​所在点。

注意

  1. 第3行是​​return quickSort(0,nums.length,nums,k);​​​
    而不是​​​return quickSort(0,nums.length-1,nums,k);​
  2. 第19行是​​return quickSort(begin+1,r,arr,k);​​​
    而不是​​​return quickSort(begin,r,arr,k);​

代码

public class Solution {
public int findKthLargest(int[] nums, int k) {
return quickSort(0,nums.length,nums,k);
}
private int quickSort(int l,int r,int[] arr, int k){
int pivot = arr[l],begin=l,end=r;
while(begin < end)
{
while(begin < end && arr[--end] >= pivot);
arr[begin] = arr[end];
while(begin < end && arr[++begin] <= pivot);
arr[end] = arr[begin];
}
int mid=begin;
arr[mid] = pivot;
if(arr.length-mid<k)
return quickSort(l,mid,arr,k);
else if(arr.length-mid>k)
return quickSort(mid+1,r,arr,k);
else
return pivot;
}
}