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; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
2021-05-06 使用jenkins从gitlab上拉取代码并打包发布到tomcat