【算法训练】LeetCode#347 前 K 个高频元素
一、描述
347. 前 K 个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
二、思路
额,如果只是想做出来,那这道题可以是“简单”难度,而不是中等难度,直接遍历计数即可。
- v1:通过一次遍历得到所有元素出现次数,再利用大顶堆做排序,然后输出前k个。
- v2:相较于v1,在得到出现次数后,构建一个小顶堆,当需要插入的时候再插入,提升性能。
三、解题
public class LeetCode347 {
public int[] topKFrequentV1(int[] nums,int k){
HashMap<Integer,Integer> map = new HashMap<>();
int[] ans = new int[k];
for (int val : nums){
map.put(val,map.getOrDefault(val,0)+1);
}
// 大根堆
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
@Override
public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
return o2.getValue()-o1.getValue();
}
});
queue.addAll(map.entrySet());
while (!queue.isEmpty() && k > 0){
ans[--k] = queue.poll().getKey();
}
return ans;
}
public int[] topKFrequentV2(int[] nums,int k){
HashMap<Integer,Integer> map = new HashMap<>();
for (int val : nums){
map.put(val,map.getOrDefault(val,0)+1);
}
// 小根堆,用int[]代替键值对,[0]key,[1]val
PriorityQueue<int[]> queue = new PriorityQueue<>(new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
for (Map.Entry<Integer,Integer> entry : map.entrySet()){
int key = entry.getKey() , val = entry.getValue();
if (queue.size() == k){
// 如果堆中已有k个元素,则比较堆顶元素与当前val的大小
if (queue.peek()[1] < val){
// 表明堆顶元素需要淘汰
queue.poll();
queue.offer(new int[]{key,val});
}
} else {
queue.offer(new int[]{key,val});
}
}
int[] ans = new int[k];
for (int i = 0 ; i < k ; ++i){
ans[i] = queue.poll()[0];
}
return ans;
}
}