leetcode347 —— n中topK && PriorityQueue(Heap) && Map遍历
题目要求:求前K个最频繁出现的数字。
1.很容易想到,使用HashMap<Integer,Integer>来存储<number,frequency>键值对
1 int n = nums.length;
2 Map<Integer, Integer> map = new HashMap<>(n);
3
4 for (int num : nums) {
5 map.put(num, map.getOrDefault(num, 0) + 1);
6 }
2.接下来非常自然的思路就是:
- 对<number,frequency>按照frequency进行降序排序
- 返回前k个<number,frequency>的number
根据题目的黑字提示:“你可以按 任意顺序 返回答案。”。可以计算出第K频繁的数的frequency,接着遍历map,返回所有frequency >= Kth的number即可:
1 Integer[] temp = map.values().toArray(new Integer[map.size()]);
2 Arrays.sort(temp);
3 int[] ans = new int[k];
4 int KthCount = temp[temp.length - k], i = 0;
5
6 for (Map.Entry<Integer, Integer> kv : map.entrySet()) {
7 if (kv.getValue() >= KthCount) {
8 ans[i++] = kv.getKey();
9 }
10 }
因为时间超过5%,想到了对map遍历时是否可以直接遍历map中的键值对,于是:
1 for (Map.Entry<Integer, Integer> kv : map.entrySet()) {
2 if (kv.getValue() >= KthCount) {
3 ans[i++] = kv.getKey();
4 }
5 }
进阶的时间要求想不出来,于是看了题解,有了以下收获:
题目最终需要返回的是前 kk 个频率最大的元素,可以想到借助堆这种数据结构,对于 kk 频率之后的元素不用再去处理,进一步优化时间复杂度。
- 求前 k 大,用小根堆,求前 k 小,用大根堆
PriorityQueue<int[]> minHeap = new PriorityQueue<>(k,
new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
//升序
return o1[1] - o2[1];
//降序
return o2[1] - o1[1];
}
});
- topk (前k大)用小根堆,维护堆大小不超过 k 即可。每次压入堆前和堆顶元素比较,如果比堆顶元素还小,直接扔掉,否则压入堆。检查堆大小是否超过 k,如果超过,弹出堆顶。复杂度是 nlogk
- 避免使用大根堆,因为你得把所有元素压入堆,复杂度是 nlogn,而且还浪费内存。如果是海量元素,那就挂了。
PriorityQueue<int[]> minHeap = new PriorityQueue<>(k,
new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
}); int count = 0
for (Map.Entry<Integer, Integer> kv : map.entrySet()) {
//前K个键值对不需要判断
if (count++ < k) {
minHeap.add(new int[]{kv.getKey(), kv.getValue()});
} else if (kv.getValue() > minHeap.peek()[1]) {
minHeap.poll();
minHeap.add(new int[]{kv.getKey(), kv.getValue()});
}
}
leetcode347 —— n中topK && PriorityQueue(Heap) && Map遍历的更多相关文章
- 去除List集合中的重复对象,Map遍历代码
/*** * 去除List<PartsInfoDTO>列表中的重复对象 ~!! * @param list * @return */ public static List<Parts ...
- jquery中的 ajax 以及map遍历
1.语法 $.ajax{ type:'get',//类型 有get post url:'',//路径 data:{name:$('#ma').val(),nameq:$('#maq').val()}, ...
- js中三个对数组操作的函数 indexOf()方法 filter筛选 forEach遍历 map遍历
indexOf()方法 indexOf()方法返回在该数组中第一个找到的元素位置,如果它不存在则返回-1. 不使用indexOf时 var arr = ['apple','orange','pea ...
- Java中Map遍历的四种方案
在Java中如何遍历Map对象 方式一 这是最常见的并且在大多数情况下也是最可取的遍历方式.在键值都需要时使用. Map<Integer, Integer> map = new HashM ...
- java中Map遍历的四种方式
在java中所有的map都实现了Map接口,因此所有的Map(如HashMap, TreeMap, LinkedHashMap, Hashtable等)都可以用以下的方式去遍历. 方法一:在for循环 ...
- Java集合中List,Set以及Map等集合体系详解
转载请注明出处:Java集合中List,Set以及Map等集合体系详解(史上最全) 概述: List , Set, Map都是接口,前两个继承至collection接口,Map为独立接口 Set下有H ...
- Java中关于HashMap的元素遍历的顺序问题
Java中关于HashMap的元素遍历的顺序问题 今天在使用如下的方式遍历HashMap里面的元素时 1 for (Entry<String, String> entry : hashMa ...
- map遍历的四种方式
原文 http://blog.csdn.net/dayanxuqun/article/details/26348277 以下是map遍历的四种方式: // 一.推荐只用value的时候用,都懂的... ...
- ES6中的Set和Map集合
前面的话 在ES6标准制定以前,由于可选的集合类型有限,数组使用的又是数值型索引,因而经常被用于创建队列和栈.如果需要使用非数值型索引,就会用非数组对象创建所需的数据结构,而这就是Set集合与Map集 ...
随机推荐
- NOIP模拟38:a
这是T1. 考场上思路与正解就差个前缀,打的线段树,因为其巨大常数快乐挂掉...... 正解复杂度是\(O(n^2m)\),其实再挂个\(log\)也能过,但是需要用常数极其优秀的树状数组 ...
- Java并发知识总结,超详细!
首先给大家分享一个github仓库,上面放了200多本经典的计算机书籍,包括C语言.C++.Java.Python.前端.数据库.操作系统.计算机网络.数据结构和算法.机器学习.编程人生等,可以sta ...
- Mysql 面试宝典
实时更新 你用过哪些数据库? mysql redis mysql 和 redis 的区别? 比较点 Mysql Redis 数据库类型 关系型 非关系型 作用 持久化层 存储需要持久化的数据,数据存在 ...
- C语言实现线程池功能
1. 线程池基本原理 2. 线程池C语言实现 2.1 线程池的数据结构 #include <stdio.h> #include <pthread.h> #include < ...
- windows系统框架
- PHP中的数组分页实现(非数据库)
在日常开发的业务环境中,我们一般都会使用 MySQL 语句来实现分页的功能.但是,往往也有些数据并不多,或者只是获取 PHP 中定义的一些数组数据时需要分页的功能.这时,我们其实不需要每次都去查询数据 ...
- TP6自带的跨域中间件无法使用的个人解决方法
使用TP6,因为需要跨域上传图片,一直不成功,网上搜了好久,方法都没解决跨域上传文件 比如下面的方式没成功 $this->app = $app; $this->request = $thi ...
- windows 中cmd一些特殊命令
chcp 65001 就是换成UTF-8代码页 chcp 936 可以换回默认的GBK chcp 437 是美国英语 shutdown -s -t 60 60秒后关机 shutdown /a ...
- Docker系列(26)- 发布镜像到阿里云容器服务
1.登录阿里云 2.找到容器镜像服务 3.创建命名空间 4.创建镜像仓库 5.上传镜像
- Linux系列(11) - PATH环境变量
前言 在Liunx当中要想执行"执行脚本"."执行文件"或者"执行命令",需要用绝对路径:因此环境变量就出来了,将路径放到环境变量中,环境变 ...