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个就是答案。
代码
2、优先队列
复杂度
时间 O(NlogK) 空间 O(K)
思路
遍历数组时将数字加入优先队列(堆),一旦堆的大小大于k就将堆顶元素去除,确保堆的大小为k。遍历完后堆顶就是返回值。
附
优先队列就是最小堆,最小值在根节点。
代码
3、快速排序
复杂度
时间 Avg O(N) Worst O(N^2) 空间 O(1)
思路
跟快速排序一个思路。先取一个枢纽值,将数组中小于枢纽值的放在左边,大于枢纽值的放在右边,最后把枢纽值放到分界点(具体请看被忽视的 partition 算法)。如果分界点后面有k-1个数,说明分界点的数就是第k个数;否则,如果分界点后的数大于k-1,则在右半边做同样的搜索;如果分界点后的数小于k-1,则在左半边做同样的搜索。
附
背景资料:被忽视的 partition 算法
实现快速排序的方法很多,最直观的就是用两个List,一个存放小于pivot,一个存放大于pivot,但是这样既低效又浪费空间,所以推荐使用partition算法。它的核心实际上就是双指针法:
begin
代表的是小于等于pivot
值的边界(不含begin
本身),end代表的是大于等于pivot的边界(不含end
本身),这样两指针逐渐往中间靠拢,最后begin==end
其位置就是pivot
所在点。
注意
- 第3行是
return quickSort(0,nums.length,nums,k);
而不是return quickSort(0,nums.length-1,nums,k);
- 第19行是
return quickSort(begin+1,r,arr,k);
而不是return quickSort(begin,r,arr,k);
代码