前K个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。347.力扣题目链接
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
示例 2:
输入: nums = [1], k = 1 输出: [1]
提示:
1 <= nums.length <= 105
k
的取值范围是[1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前
k
个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n)
,其中 n
是数组大小。
【思路】
本题主要涉及三部分内容:
- 要统计元素出现的频率
- 对频率进行排序
- 找出前K个高频元素
统计元素出现的频率,可以通过Map来实现;然后是对出现的频率进行排序,这里使用优先级队列。
/*Comparator接口说明: * 返回负数,形参中第一个参数排在前面;返回正数,形参中第二个参数排在前面 * 对于队列:排在前面意味着往队头靠 * 对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆), * 从队头到队尾按从大到小排就是最大堆(大顶堆)--->队头元素相当于堆的根节点 * */ class Solution { public int[] topKFrequent(int[] nums, int k) { // 优先级队列 // lambda表达式设置优先级队列从大到小存储o1-o2为从大到小,o2-o1反之 PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]); int[] res = new int[k]; // 答案数组为k个元素 Map<Integer, Integer> map = new HashMap<>(); //记录元素出现次数 for (int num: nums) map.put(num, map.getOrDefault(num, 0) + 1); for (var x : map.entrySet()) { // entrySet获取k-v Set集合 // 将kv转化为数组 int[] tmp = new int[2]; tmp[0] = x.getKey(); tmp[1] = x.getValue(); pq.offer(tmp); if (pq.size() > k) { pq.poll(); } } for (int i = 0; i < k; i++) { res[i] = pq.poll()[0]; // 获取优先队列里的元素 } return res; } }