堆:数组中的第K个最大数
题目描述:给定一个整数数组,返回数组中的第K个最大数。
示例 1:
输入: [3,2,1,5,6,4],k = 2 输出: 5 说明:降序排序之后:[6,5,4,3,2,1] =》第2个最大数是5
示例 2:
输入: [3,2,3,1,2,4,5,5,6],k = 4 输出: 4 说明:降序排序之后:[6,5,5,4,3,3,2,2,1] =》第4个最大数是4
题解1:排序求解
class Solution {public int findKthLargest(int[] nums, int k) {// 方法一:先排序,返回nums[n-k]// [98,1,0,23,24] => [0,1,23,24,98]Arrays.sort(nums); // 默认升序;k=2;return 24return nums[nums.length - k];}
}
题解2:最小堆
维护个数为K的最小堆,堆顶元素就是第K个最大数
class Solution {public int findKthLargest(int[] nums, int k) {// 方法二:最小堆求解PriorityQueue<Integer> heap = new PriorityQueue<Integer>((n1, n2) -> n1 - n2); for (int n : nums) {heap.add(n);if (heap.size() > k) {heap.poll();}}// 最小堆堆顶就是答案return heap.poll();}
}
题解3:快速选择(三路分区)
class Solution {public int findKthLargest(int[] nums, int k) {// 方法三:基于快排List<Integer> numList = new ArrayList<>();for (int num : nums) {numList.add(num);}return quickSelect(numList, k);}int quickSelect(List<Integer> nums, int k) {// 随机选择基准数Random rand = new Random();int pivotNum = nums.get(rand.nextInt(nums.size()));// 将大于、小于、等于pivotNum的元素划分至big,small,equal中List<Integer> big = new ArrayList<>();List<Integer> small = new ArrayList<>();List<Integer> equal = new ArrayList<>();for (int num : nums) {if (num > pivotNum) {big.add(num);} else if (num < pivotNum) {small.add(num);} else {equal.add(num);}}// 第k大元素在big中,递归划分// big包含所有大于pivotNum的元素,这些元素在整体排序中位于前big.size()个位置// 如果big.size()=5,那么第1~5大的数都在big中if (k <= big.size()) {return quickSelect(big, k);}// 第k大元素在small中,递归划分// big.size() + equal.size():这个值表示大于等于pivotNum的元素个数// 如果k > 这个值,说明第K大元素比pivot小,在small中if (big.size() + equal.size() < k) {// 在small中药重新计算k值,因为small中的最大元素在整个数组中排第(nums.size() - small.size() + 1)大return quickSelect(small, k - (big.size() + equal.size()));}// 第k大元素在equal中,直接返回return pivotNum;}
}
练习地址:https://leetcode.cn/problems/kth-largest-element-in-an-array/?envType=study-plan-v2&envId=top-100-liked