- 前 K 个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。
1.利用了最小堆实现了对map 的排序
只将key放入到了优先队列中
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int len= nums.length;
if(len == 0 || k < 0) return new int[]{};
int[] res = new int[k];
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < len; i++){
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
//对map进行排序,之前的那个方法无效,那个是针对key进行排序,这个要针对value排序
PriorityQueue<Integer> pq = new PriorityQueue<>(k + 1, new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);//按照value的最小堆
}
});
//记住,最小堆,最终保存的是最大的几个值
for(Integer key : map.keySet()){
if(pq.size() < k){//这种写法比L215那种方法更好些,不需要分开写了
pq.add(key);
}else{
pq.add(key);
pq.poll();//其实不设置大小也是可以的
}
}
for(int i = 0; i < k ; i++){
res[i] = pq.poll();
}
return res;
}
}
2.桶排序,用到一个新的数据结构,list数组,比较新颖
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int len= nums.length;
if(len == 0 || k < 0) return new int[]{};
int[] res = new int[k];
HashMap<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < len; i++){
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
//仍然先用map来记录
List<Integer>[] arr = new List[len + 1];//集合数组
for(int key : map.keySet()){
int times = map.get(key);
//注意还没有List生产
if(arr[times] == null) arr[times] = new ArrayList<>();
arr[times].add(key);
}
//即使出现频率相同也是满足的,因为是list数组,但是用数组接收不太方便
//接下来就不太好做了,但是思想还是不错的
}
}