(堆)347. 前 K 个高频元素
题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入:nums = [1,1,1,2,2,3], k = 2
输出:[1,2]
示例 2:
输入:nums = [1], k = 1
输出:[1]
示例 3:
输入:nums = [1,2,1,2,1,2,3,1,3,2], k = 2
输出:[1,2]
提示:
1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。
思路
使用Map存储每个数值的频率,记为map(这一步也可以使用数组操作)
- key:nums里面的数值num
- value:对应num出现的频率
之后再使用数组array存储 此频率的所有元素
- 数组下标为频率
- 数组的值:为此频率的所有元素
最终要求的值res:array下标从大到小偏离,直到res被塞满
算法
class Solution {public int[] topKFrequent(int[] nums, int k) {// key: num;value:num的频率Map<Integer, Integer> map = new HashMap<>();for (int num : nums) {if (!map.containsKey(num)) {map.put(num, 1);} else {map.put(num, map.get(num) + 1);}}// 堆排序// 将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标List<Integer>[] array = new ArrayList[nums.length + 1];for (int num : map.keySet()) {// 频率作为下标int fre = map.get(num);if (array[fre] == null) {array[fre] = new ArrayList<>();}array[fre].add(num);}int[] res = new int[k];// 倒序遍历数组获取出现顺序从大到小的排列for (int i = array.length - 1, j = 0; i >= 0 && j < k; i--) {if (array[i] == null)continue;List<Integer> list = array[i];for (int num : list) {res[j++] = num;}}return res;}
}