LeetCode215 KthLargestElementInAnArray
题目描述
在未排序的数组中找到第 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
解答
解法一:利用快速排序
假设数组长度为n。利用快速排序思想,但不用将所有数组元素全部排好序。只需要找到当前关键字所在的索引为n-k就可以(此时,该位左边的值都比关键字小,右边的都比关键字大),但是对于单独的左右两边来说可以是无序的。swap(函数为自定义交换函数)。
public static void fastSort(int[] a, int left, int right, int k){
if (left>=right)
return;
int key = a[left];
int iLeft = left;
int iRight = right;
while (iLeft<iRight){
while (a[iRight]>=key && iLeft<iRight){
iRight--;
}
while (a[iLeft]<=key && iLeft<iRight){
iLeft++;
}
swap(a, iRight,iLeft);
}
swap(a,iLeft,left);
if (iLeft<k){
fastSort(a, iLeft+1, right, k); //往右边找
}else if(iLeft>k){
fastSort(a, left,iLeft-1,k);
}
}
解法二:利用堆排序
假设数组长度为n。利用堆排序,首先构建一个顶点个数为K的小顶堆,注意是小顶堆。构建完以后,将堆顶元素nums[0]与nums[i]进行比较,若是nums[i]比较大,则与0位置处交换,再重新调整堆,i+1。重复这一步,直到i遍历完整个数组。
//解法二:利用堆排序,构建结点个数为k小顶堆,不断进行调整,最后的小顶堆顶点就是答案
public static int solve2(int[] nums, int k){
//构建小顶堆
for (int i=k/2-1;i>=0;i--){
adjustHeap(nums,i,k);
}
//将小顶堆堆顶元素与索引为i的元素进行比较,若是nums[i]较大,则交换位置,将其放置堆顶,再调整推。
for (int i=k;i<nums.length;i++){
if (nums[0]<nums[i]){
swap(nums,0,i);
adjustHeap(nums,0, k);
}
}
return nums[0];
}
//对索引为i处的结点往下调整。index:循环不变量,表示的是当前需要调整的结点的索引
public static void adjustHeap(int[] a, int index, int length){
//取出当前元素
int temp = a[index];
//遍历左右子树中结点值更小的那个
for (int k= 2*index+1; k<length; k=2*k+1){
if (k+1<length && a[k]>a[k+1])
k=k+1;
//与当前结点作比较,孩子结点更小,则交换,否则调整结束·
if (a[k]<temp){
a[index]=a[k];
index=k;
}else
break;
}
a[index]=temp;
}