Kth Largest Element
Description
Find K-th largest element in an array.
Notice
You can swap elements in the array
Example
In array [9,3,2,4,8], the 3rd largest element is 4.
In array [1,2,3,4,5], the 1st largest element is 5, 2nd largest element is 4, 3rd largest element is 3 and etc.
Challenge
O(n) time, O(1) extra memory.
实现思路一:基于优先队列
我们可以先往数组中存k个数,然后遍历从k开始遍历数组元素,如果数组元素小于优先队列中最小的数,则踢出队列最小数,放入数组元素。
直到遍历完,我们就得到最大的k个数,然后取出这个k个数中最小的,就是我们要的第k个最大数。
算法实现如下:
import java.util.Map.Entry;
class Solution {
/*
* @param k : description of k
* @param nums : array of nums
* @return: description of return
*/
public int kthLargestElement(int k, int[] nums) {
// write your code here
PriorityQueue<Integer> queue = new PriorityQueue<>();
int length = nums.length;
for(int i = 0 ; i < k ; i ++){
queue.offer(nums[i]);
}
for(int i = k ; i < length; i++){
if(queue.peek() < nums[i]){
queue.poll();
queue.offer(nums[i]);
}
}
return queue.peek();
}
};
实现思路二:基于剪枝快排
利用有限队列,我们的额外空间复杂度为o(k),时间复杂度为n*log(k)。
我们还有另一种实现方法,是基于快排,在每次选出基数并经过一次从大到小排序后,然后判断:
1. 如果基数就在第k-1位,则基数即为所求
2. 若在第k-1位后面,则取基数往后,继第k-1位
3. 若在第k-1位前面,则取基数往前,找第k-1位
经过1、2、3步不断迭代,最终必能找到最大的第k个数
具体实现代码如下所示:
class Solution {
/*
* @param k : description of k
* @param nums : array of nums
* @return: description of return
*/
public int kthLargestElement(int k, int[] nums) {
return partition(nums,k-1,0,nums.length-1);
}
public int partition(int[] nums, int k, int left, int right){
if(left >= right){
return nums[left];
}
int begin = left, end = right;
int flag = nums[begin];
while(begin < end){
while(begin < end && nums[end] <= flag){
end--;
}
nums[begin] = nums[end];
while(begin < end && nums[begin] > flag){
begin++;
}
nums[end] = nums[begin];
}
nums[begin] = flag;
if(begin == k){
return nums[begin];
}else if(begin < k){//最大k数在右边
return partition(nums,k,begin+1,right);
}else{//在左边
return partition(nums,k,left,begin-1);
}
}
}