top k 问题 Java解决代码

top k问题:从10亿个数中选出最大的1万个数,处理方式:用小顶堆,先用1万个数建立小顶堆,再把剩余数从小顶堆里过一遍,每次与堆顶元素比较,小顶堆的堆顶元素是最小的,如果比堆顶元素小就舍弃,如果比堆顶元素大就替换堆顶元素,重新调整为小顶堆,继续比较直到10亿条数据比完,堆里剩下的就是最大的1万个数。
如果是从大量元素里挑出最小的前k个,就建立容量为k的大顶堆,堆顶是最大的元素,剩余元素跟堆顶元素比较,如果堆顶元素大就替换掉。
大顶堆,小顶堆如何建立,在java代码中有现成的堆数据结构PriorityQueue(也可以用数组自己建立堆数据结构,替换堆顶元素重新排序需要自己写方法实现),默认是小顶堆,想要大顶堆就重写compare方法

一: 用PriorityQueue找出前k个最小元素:

复制代码
public static int[] topK(int[] arr,int k){
// 创建一个大小为 k的大根堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
for (int i = 0; i < arr.length; i++) {
if (i < k){
// 放入前 k 个元素
maxHeap.offer(arr[i]);
}else{
// 从第 k+1个元素开始进行判断是否要入堆
if (maxHeap.peek() > arr[i]){
maxHeap.poll();
maxHeap.offer(arr[i]);
}
}
}
int[] ret = new int[k];
for (int i = 0; i < k; i++) {
ret[i] = maxHeap.poll();
}
return ret;
}
复制代码

 

二 top k找出出现频率最大的前k条:

先用hash结构获取元素值和出现的次数,再将hash结构放到堆中用频次比较:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public int[]topKFrequent(int[]nums,int k){
//occurrences的key是元素值,value是元素出现的次数
Map<Integer,Integer> occurrences = new HashMap<Integer,Integer>();
for(int num:nums){
//occurrences.getOrDefault(key,def)是根据key获取value值,如果找不到key就返回默认值def
//第一次occurrences为空都找不到,值是1,后面能找到了每次加一
occurrences.put(num,occurrences.getOrDefault(num,0)+1);
}
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>(){
//PriorityQueue是Java的堆数据结构,这里存放的是整形数组,下标0存key,下标1存出现次数
//重写compare方法,指定用频次比较
public int compare(int[]m,int[]n){return m[1]- n[1];}
});
for(Map.Entry<Integer,Integer>entry : occurrences.entrySet()){
int num=entry.getKey(),count=entry.getValue();
if(queue.size()==k){
if(queue.peek()[1]<count) {//堆顶元素下标1是频次,和数组的其他元素的频次比较
//删除堆顶元素
queue.poll();
//堆中加入元素
queue.offer(new int[]{num, count});
}
}else{
//堆中加入元素
queue.offer(new int[]{num, count});
}
}
 
int[]ret = new int[k];
for(int i=0;i<k; ++i){
ret[i]= queue.poll()[1];
}
return ret;
}

  

posted @   杨吃羊  阅读(137)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2021-05-06 使用jenkins从gitlab上拉取代码并打包发布到tomcat
点击右上角即可分享
微信分享提示