数组中的第K个最大元素 Leetcode 215
思路
可以把小顶堆 pq 理解成一个筛子,较大的元素会沉淀下去,较小的元素会浮上来;当堆大小超过 k 的时候,我们就删掉堆顶的元素,因为这些元素比较小,而我们想要的是前 k 个最大元素嘛。
PriorityQueue 被用来实现一个最小堆,用于查找整数数组中的第 k 大元素。每次向堆中插入元素后,如果堆的大小超过了 k,则移除堆顶元素,保持堆的大小为 k。最终,堆顶元素即为第 k 大元素。
二叉堆:
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<>();
for(int num:nums){
pq.offer(num);
if(pq.size()>k){
pq.poll();
}
}
return pq.peek();
}
}
也可以实现O(n)的时间复杂度
class Solution {
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
private int quickSelect(int[] nums, int left, int right, int targetIndex) {
if (left == right) return nums[targetIndex];
int pivot = nums[left];
int i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= pivot) j--;
if (i < j) nums[i++] = nums[j];
while (i < j && nums[i] <= pivot) i++;
if (i < j) nums[j--] = nums[i];
}
nums[i] = pivot;
if (targetIndex <= i) return quickSelect(nums, left, i, targetIndex);
else return quickSelect(nums, i + 1, right, targetIndex);
}
}
Leetcode 347 前 K 个高频元素
思路
和之前215一致,使用PriorityQueue做,只是结合了HashMap
class Solution {
public int[] topKFrequent(int[] nums, int k) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int num:nums){
map.put(num,map.getOrDefault(num,0)+1);
}
PriorityQueue<Map.Entry<Integer,Integer>>
pq = new PriorityQueue<>((entry1,entry2)->{return entry1.getValue().compareTo(entry2.getValue());
});
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
pq.offer(entry);
if(pq.size()>k){
pq.poll();
}
}
int[] res = new int[k];
for(int i=k-1;i>=0;i--){
res[i]=pq.poll().getKey();
}
return res;
}
}