在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和
k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和
k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
先来个暴力点的通用方法:
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length-k];
}
}
当然也可以采用PrioritQueue:
如果不明白优先队列:
优先队列中的元素可以按照任意顺序插入,却总是按照排序的顺序进行检索。也就是说,无论何时调用remove()\poll()方法,总会获得但当前优先队列中的最小元素。然而优先队列并没有对所有的元素进行排序。如果用迭代的范式处理这些元素,并不需要对他们进行排序。
优先队列使用了一个优雅且高效的数据结构,称为堆(heap)。堆是一个可以自我调整的二叉树,对树执行添加(add\offer)和删除(remove\poll)操作可以让最小的元素移动到根,而不必花费时间对元素进行排序。
哎呀说了这么多:反正priorityQueue这个数据结构 你无论remove、poll、删的是队中的最小(优先级最小)元素,无论什么时候peek的取的是队列中的最小(优先级最小)元素,无论你怎么加元素 add、offer 加后、这个队列一直保持有序、
class Solution {
public int findKthLargest(int[] nums, int k) {
Queue<Integer> q =new PriorityQueue<Integer>(k);
for(int i =0;i<nums.length;i++){
if(q.size()<k){ //将优先队列(k)填满
q.offer(nums[i]);
}else{
if(nums[i]>q.peek()){ //peek总取出队列中最小元素
q.poll(); //poll总删除队列中最小元素;
q.offer(nums[i]); //将这个元素加入队列
}
}
}
return q.peek();
}
}
当然也可以使用快速排序:
class Solution {
public void swap(int[] nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public int parrtion(int[] nums,int p,int r){
int x = nums[r];
int i = p-1;
for(int j = p;j<r;j++){
if(nums[j]<x){
i++;
swap(nums,i,j);
}
}//end of for
swap(nums,r,i+1);
return i+1;
}
public void quicksort(int[] nums,int p,int r){
if(p<r){
int q = parrtion(nums,p,r);
quicksort(nums,p,q-1);
quicksort(nums,q+1,r);
}
}
public int findKthLargest(int[] nums, int k) {
quicksort(nums,0,nums.length-1);
return nums[nums.length-k];
}
}
可看的出来将数组分割为两部分的时候我们完全只考虑存在倒数第k大数的数组部分,而另一部分就不用去管了
优化后的快排思想:
class Solution {
public void swap(int[] nums,int i,int j){
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
public int parrtion(int[] nums,int p,int r){
int x = nums[r];
int i = p-1;
for(int j = p;j<r;j++){
if(nums[j]>x){ //按从大到小排 排序后nums[k-1] 即为所求
i++;
swap(nums,i,j);
}
}//end of for
swap(nums,r,i+1);
return i+1;
}
public int quicksort(int[] nums,int p,int r,int k){
if(p>=r) return nums[p];
int q = parrtion(nums,p,r);
if(q ==k-1) return nums[q];//如果找到k-1位置 返回第k大的数
else if(q>=k){ //如果q>=k说明第k大的数在数组左半部分
return quicksort(nums,p,q-1,k);//只在左边找就可以了
}else{
return quicksort(nums,q+1,r,k);//在右边找
}
}
public int findKthLargest(int[] nums, int k) {
return quicksort(nums,0,nums.length-1, k);
}
}