在未排序的数组中找到第 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大的元素。本文没有使用java封装好的类,手动建堆。
建堆过程:堆的结构其实是一个完全二叉树,大顶堆就是当前节点大于其子节点,小根堆当前节点小于其子节点,我们可以用数组储存。
以大顶堆为例,其中主要包含shiftup()
,shift down()
两个函数shiftup()
为上移当前节点直到满足当前节点小于其父节点。shiftdown()
为下移当前节点直到为结尾或者当前节点大于其子节点。
1.shiftup()
函数在大根堆中是在建堆过程中使用,每遍历到一个新元素,对其进行shiftup()
函数。
2.shiftdown()
函数用在将整个大顶堆建好后,排序时候使用,将根节点与末尾节点互换,互换后的根节点打破了大顶堆的特性就会执行shiftdown()
,直到所有元素排序完。
public int findKthLargest(int[] nums, int k) {
buildheap(nums);
int len=nums.length-1;
while(k>1){
swap(0,len,nums); //排序首尾元素互换
len--; //下移时不能包含排序好的元素
shiftdown(nums,0,len);
k--;
}
return nums[0];
}
public void buildheap(int[] nums){ //建堆
for(int i=1;i<nums.length;i++)
shiftup(i,nums);
}
public void shiftup(int i,int[] nums){ //上移操作
while(i>0&&nums[i]>nums[(i-1)/2]){
swap(i,(i-1)/2,nums);
i=(i-1)/2;
}
}
public void shiftdown(int[] nums,int i,int end){ //下移操作
int left=(i*2)+1;
int right=(i*2)+2;
int temp=0;
while(right<=end){
if(nums[left]>nums[right])
temp=left;
else
temp=right;
if(nums[i]>nums[temp])
break;
swap(i,temp,nums);
i=temp;
left=(i*2)+1;
right=(i*2)+2;
}
if(left<=end){
if(nums[i]<nums[left]){
swap(i,left,nums);
}
}
}
public void swap(int a,int b,int[] nums){
int temp=nums[a];
nums[a]=nums[b];
nums[b]=temp;
}