前一篇博客中写到了排序算法,其中包含一个堆排序,因此本篇博客讲解堆这个数据结构及其应用。

关于最大堆最小堆以及初始建堆和整理堆在上篇博客中有提及,此处不再赘述。下面讲解一个堆的重要应用,求n个数中前k个大的数,一般思路是将n个数排序,取前k个数,但当n的数量庞大无法加载到内存时,需要另外一种思路,即利用堆,只维护k个树的大小而不需维护全部。

具体的思路是:先建一个k个数的小堆,然后从k+1个数往后的值与堆顶元素比较,若此数比堆顶元素大,就将堆顶元素用这个数替换,然后重新调整堆,以此向后重复上述过程,直到将N个数比较完成,那么此时组成这个堆的k个元素就是前k个大的数。

下面以leetcode上的题为例,实现这个求解过程。

347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements.

For example,

Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note:

  • You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
  • Your algorithm's time complexity must be better than O(n log n), where n is the array's size.

java中的优先队列PriorityQueue是一个具有小根堆性质的数据结构,并且可以通过提供comparator比较器实现大根堆或自定义排序。本题中要求统计数字出现次数,使用hashmap,并自定义数据结构完成数字到出现次数的一一映射,通过上面的思路,维护大小为k的小根堆,最后逆向输出。

class KeyValue{Integer key;Integer value;public KeyValue(Integer key,Integer value) {this.key=key;this.value=value;}}public List<Integer> topKFrequent(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<>();//统计数字出现频率for(int i=0;i<nums.length;i++) {if(map.containsKey(nums[i])) {map.put(nums[i],map.get(nums[i])+1);} else {map.put(nums[i],1);}}Iterator iter = map.entrySet().iterator();Queue<KeyValue> queue = new PriorityQueue<>(k,new Comparator<KeyValue>() {public int compare(KeyValue value1,KeyValue value2) {return value1.value-value2.value;}    });int cnt=0;while(iter.hasNext()) { //对hashmap中元组遍历Map.Entry entry = (Map.Entry) iter.next();KeyValue tmp = new KeyValue((Integer) entry.getKey(),(Integer) entry.getValue());if(cnt<k) { //k大小优先队列queue.add(tmp);} else if(tmp.value>queue.peek().value) {   //比堆顶大,替换堆顶queue.poll();queue.add(tmp);}cnt++;}List<Integer> ret = new ArrayList<>();//小根堆逆向输出,频率大的在前  for(int i=0;i<k;i++) {ret.add(0,queue.poll().key);}return ret;}

[leetcode]堆排序 求前k大的数相关推荐

  1. 信息学奥赛一本通(1235:输出前k大的数)——堆排序

    1235:输出前k大的数 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 12715     通过数: 4043 [题目描述] 给定一个数组,统计前k大的数并且把这 ...

  2. 算法题 求第K大的数

    题目描述:在乱序数组中求第K大的数 思路:立刻想到的是当然先排序然后取数.但是提问者明显不是想这么解.上网查了下原来是快排思路. 利用快排的思想,从数组arr中随机找出一个元素X,把数组分成两部分ar ...

  3. C语言(CED)输出前k大的数(分治法/局部快速排序):给定一个数组,统计前k大的数并且把这k个数从大到小输出。

    )输出前k大的数(分治法/局部快速排序):给定一个数组,统计前k大的数并且把这k个数从大到小输出. [输入] 第一行包含一个整数n,表示数组的大小. 第二行包含n个整数,表示数组的元素,整数之间以一个 ...

  4. 输出前k大的数(信息学奥赛一本通-T1235)

    [题目描述] 给定一个数组,统计前k大的数并且把这k个数从大到小输出. [输入] 第一行包含一个整数n,表示数组的大小.n < 100000. 第二行包含n个整数,表示数组的元素,整数之间以一个 ...

  5. (分治)7617:输出前k大的数

    描述  给定一个数组,统计前k大的数并且把这k个数从大到小输出. 输入  第一行包含一个整数n,表示数组的大小.n < 100000.  第二行包含n个整数,表示数组的元素,整数之间以一个空格分 ...

  6. C++ 输出前K大的数

    1:输出前k大的数 查看 提交 统计 提问 总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB 描述 给定一个数组,统计前k大的数并且把这k个数从大到小输出. ...

  7. 无序数组求第k大的数 python_整数无序数组求第K大数

    import java.util.Scanner; /** * 类似与求第k小的问题 * 求第k大相当于求第n-k+1小,n为数组长度 * * 著名的BFPRT算法可保证在线性时间内得到结果. * h ...

  8. 【Leetcode】两个有序数组,求第k大的数

    双指针: def func(num1,num2,k):i,j,n = 0,0,0while i<len(num1) or j<len(num2):n += 1if i<len(num ...

  9. 利用向量叉积求三角形的面积(+STL:nth_element求第K大的数)

    牛客寒假算法集训营2 https://ac.nowcoder.com/acm/contest/327/A A.处女座的签到题 题目描述 平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多 ...

最新文章

  1. 将一个一维数组转化为二进制表示矩阵。例如_算法之矩阵最大区域问题
  2. Java 线程同步 synchronized
  3. Navicat for SQLite 15中文版
  4. 蓝桥杯第六届决赛真题大全解(java版本)
  5. 【译】Diving Into The Ethereum VM Part 4 - How To Decipher A Smart Contract Method Call
  6. 软设考试笔记--UML建模
  7. 卷积的物理意义(经典)
  8. Linux内核的l2tp实现,Linux Kernel gdth实现内核内存破坏漏洞
  9. 计算机信息加工的类型及举例,3.1.2计算机信息加工的过程和类型
  10. 接入淘宝API(PHP版本)
  11. jsoup Java HTML解析器
  12. 动态规划时间复杂度_算法分析与设计之动态规划
  13. HEX2BIN不能在win7_64位下执行的Keil官方解决方案
  14. 小白教程 微信小程序 官方示例Demo下载及运行
  15. 网络安全-终端安全检测和防御技术
  16. 绝对值线性化的两种方式
  17. Win7电脑如何关闭智能卡服务功能--win10专业版
  18. 工业镜头倍率及视场范围、焦距的计算方法
  19. [分享]高手是怎样炼成的:精妙SQL语句介绍
  20. 基于高光谱影像的农作物检测应用简介

热门文章

  1. MacBook使用技巧:苹果笔记本的PrintScreen截屏快捷键使用方法
  2. 蓝桥杯矩阵翻转java_矩阵翻转硬币 蓝桥杯
  3. P卡不安全了?还有什么卡可以绑PayPal / eBay扣费?
  4. HLSL内置函数,及HLSL与GLSL的对应函数
  5. 前端页面select标签
  6. error: subprocess-exited-with-error完美解决Weditor安装不了问题
  7. java方法——方法的定义
  8. 一次Nexus启动失败
  9. blocking与non_blocking
  10. Java反射获取对象的属性值