题目描述
解题思路
根据频率大小排序,那么可以使用哈希表来对频率进行统计,在对频率进行排序。
那么问题来了,定义一个大小为k的大顶堆,在每次移动更新大顶堆的时候,每次弹出都把最大的元素弹出去了,那么怎么保留下来前K个高频元素呢。
而且使用大顶堆就要把所有元素都进行排序,那能不能只排序k个元素呢?
所以我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。
/*** 使用小顶堆实现** @param nums* @param k* @return*/public int[] topKFrequent(int[] nums, int k) {int[] res = new int[k];HashMap<Integer, Integer> map = new HashMap<>();// 将出现的值和频率使用map封装for (int i = 0; i < nums.length; i++) {map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);}// 放入集合中方便遍历到队列中Set<Map.Entry<Integer, Integer>> entries = map.entrySet();// 创建优先队列(小顶堆)PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<Map.Entry<Integer, Integer>>((o1, o2) -> {return o1.getValue() - o2.getValue();});// 将map入队for (Map.Entry<Integer, Integer> entry : entries) {queue.offer(entry);// 如果队列中的个数大于k,需要将多余的出队,此时是小顶堆,最小的在队首,所以直接出队即可if (queue.size() > k) {queue.poll();}}// 取出队列中的所有元素,即为频率前k个元素for (int i = 0; i < k; i++) {res[i] = queue.poll().getKey();}return res;}
