题目:
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
题解:
这道题目主要涉及到如下三块内容:
- 要统计元素出现频率
- 对频率排序
- 找出前K个高频元素
首先统计元素出现的频率,这一类的问题可以使用map来进行统计。
然后是对频率进行排序,这里我们可以使用一种 容器适配器就是优先级队列。
我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。如果用大顶堆,每次弹出都把最大的元素弹出去了。这里我们要让小顶堆保持k个元素,每次超过k个就弹出最小的,没超过就添加。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> occurrences = new HashMap<>();
for (int num : nums) {
occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
}
// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
// 根据map的value值正序排,相当于一个小顶堆
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() { //自定义小顶堆
public int compare(int[] m, int[] n) {
return m[1] - n[1];
}
});
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (queue.size() == k) { //让队列保持k个,当前进来的是第k+1个,和队列最小的比较
if (queue.peek()[1] < count) {
queue.poll();
queue.offer(new int[]{num, count});
}
} else { //队列不满k个,继续添加
queue.offer(new int[]{num, count});
}
}
int[] ret = new int[k];
for (int i = 0; i < k; i++) {
ret[i] = queue.poll()[0];
}
return ret;
}
}
参考:代码随想录