目录
题目描述
在未排序的数组中找到第 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 ≤ 数组的长度。
解法1:堆排序
解题思路
堆排序比较基本过程:把非叶子节点A下的子节点(A1,A2)的最大值(设为A1)和A比较。A1大于A的话,A1和A互换,否则不互换。在执行的过程中较小的值被逐层下移,下面对对堆排序过程的描述。
代码实现
用数组来记录堆,设非叶子节点数组下标为i,那么它的左右子节点的下标分别为 2*i+1 和 2*i+2,
倒数第一个非叶子节点下标为 heapSize/2-1
public class LeetCode215数组中的第K个最大元素 {
public static void main(String[] args) {
int nums[] = { 3, 2, 3, 1, 2, 4, 5, 5, 6 };
LeetCode215数组中的第K个最大元素 a = new LeetCode215数组中的第K个最大元素();
System.out.println(a.findKthLargest(nums, 4));
}
public int findKthLargest(int[] nums, int k) {
int heapSize = nums.length;
// heapSize个元素原地建堆
buildMaxHeap(nums, heapSize);
// 遍历最后k个元素,把堆顶和堆最后一个交换,交换后重新堆化
// 此时nums[0]已经是数组中最大的数了,还需要交换k-1次,才能得到topk
//所以循环的次数为k-1
for (int i = nums.length - 1; i >= nums.length - k + 1; --i) {
swap(nums, 0, i);
--heapSize;
maxHeapify(nums, 0, heapSize);
}
return nums[0];
}
// 建堆,从倒数第一个非叶子节点开始堆化,倒数第一个非叶子节点下标为 heapSize/2-1
public void buildMaxHeap(int[] a, int heapSize) {
for (int i = heapSize / 2 - 1; i >= 0; --i) {
maxHeapify(a, i, heapSize);
}
}
// 堆化递归写法
// 父节点下标i,左右子节点的下标分别为 2*i+1 和 2*i+2
public void maxHeapify(int[] a,