题目链接

https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&tqId=11182&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

题目描述

从无序序列,找到最小topk个元素。

解题思路

使用大根堆维护最小topk个元素:

- 首先前k个元素建立大根堆(从最后一个非叶节点(数组长度/2-1,结点从0计:大致是最后一个节点j与最后一个非叶节点i满足j=2i+1或j=2i+2,PS数组长度len=j+1,大概是有一些取整的原因设计,总之验证这是对的)至根节点(数组第一个元素)调整)。

- 之后维护这个最小k个元素的大根堆(比较后面的元素与根顶元素,若新元素小则替换掉堆顶元素,并进入调整)。

- 最终堆中元素即为所求。

查找topk时间复杂度:O(nlogk)。

相关知识:堆排序

堆的定义

堆是具有以下性质的完全二叉树:

每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。

用数组表示一个堆结构,堆的定义就是:(结点从0计)

大根堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小根堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

堆排序步骤

第一步:建堆:从最后一个非叶节点(数组长度/2-1,结点从0计。推导:最后一个节点下标j与最后一个非叶节点i的关系满足j=2i+1或j=2i+2=>i=j/2-1或j/2-0.5,)至根节点(数组第一个元素)调整。

第二步:反复执行交换、调整:将堆顶元素与树最后一个叶节点交换,从上至下调整剩余节点为堆(称为筛选);再将堆顶元素与最后一个叶节点交换...直到所有元素组成序列。大根堆对应升序,小根堆对应降序。

堆排序特点

  • 时间复杂度:平均、最好、最坏均为O(nlogn)
  • 相比快排,堆排序的最坏时间复杂度更优,这是堆排序最大的优点。所以堆排序适合记录数n较大的文件,不适合记录数较小的文件。
  • 对深度为K的堆,筛选算法关键字比较次数至多为2(K-1);则在建n个元素,深度为h的堆时,总共进行的关键字比较次数不超过4n(公式见数据结构严蔚敏P282底栏??);又,n个结点的完全二叉树深度为log2n」+1,所以最坏时间复杂度O(nlogn).

堆排序参考链接

https://www.cnblogs.com/chengxiao/p/6129630.html

代码

  1. import java.util.*;
  2. public class Solution {
  3. public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
  4. ArrayList<Integer> maxRootHeap = new ArrayList<Integer>();
  5. if(k<1||k>input.length){
  6. return maxRootHeap;
  7. }
  8. for(int i=0;i<k;++i) {
  9. maxRootHeap.add(input[i]);
  10. }
  11. //建堆
  12. buildMaxRootHeap(maxRootHeap);
  13. //调整
  14. for(int i=k;i<input.length;++i) {
  15. if(input[i]<maxRootHeap.get(0)) {
  16. maxRootHeap.set(0, input[i]);
  17. heapify(maxRootHeap,0,k-1);
  18. }
  19. }
  20. return maxRootHeap;
  21. }
  22. private void buildMaxRootHeap(ArrayList<Integer> maxRootHeap) {
  23. for(int i=maxRootHeap.size()/2-1;i>=0;--i) {
  24. heapify(maxRootHeap,i,maxRootHeap.size()-1);
  25. }
  26. }
  27. //调整以index索引为根节点的堆
  28. private void heapify(ArrayList<Integer> maxRootHeap,int index,int heapSize) {//heapSize 指堆最后一个节点的索引
  29. int lIdx=2*index+1;
  30. int rIdx=2*index+2;
  31. int maxIdx=index;
  32. while(lIdx<=heapSize) {
  33. if(maxRootHeap.get(lIdx)>maxRootHeap.get(index)) {
  34. maxIdx=lIdx;
  35. }
  36. if(rIdx<=heapSize&&maxRootHeap.get(rIdx)>maxRootHeap.get(maxIdx)) {
  37. maxIdx=rIdx;
  38. }
  39. if(maxIdx!=index) {
  40. swap(maxRootHeap,index,maxIdx);
  41. }
  42. else {
  43. break;
  44. }
  45. index=maxIdx;
  46. lIdx=2*index+1;
  47. rIdx=2*index+2;
  48. }
  49. }
  50. private void swap(ArrayList<Integer> heap,int idx1,int idx2) {
  51. int temp=heap.get(idx1);
  52. heap.set(idx1,heap.get(idx2));
  53. heap.set(idx2, temp);
  54. }
  55. }

[程序员代码面试指南]数组和矩阵问题-找到无序数组中最小的k个数(堆排序)的更多相关文章

  1. 《程序员代码面试指南》第八章 数组和矩阵问题 找到无序数组中最小的k 个数

    题目 找到无序数组中最小的k 个数 java代码 package com.lizhouwei.chapter8; /** * @Description: 找到无序数组中最小的k 个数 * @Autho ...

  2. 程序员代码面试指南:IT名企算法与数据结构题目最优解

      第1章栈和队列 1设计一个有getMin功能的栈(士★☆☆☆) 1由两个栈组成的队列(尉★★☆☆) 5如何仅用递归函数和栈操作逆序一个栈(尉★★☆☆) 8猫狗队列(士★☆☆☆)10用一个栈实现另一 ...

  3. 【算法】数组与矩阵问题——找到无序数组中最小的k个数

    /** * 找到无序数组中最小的k个数 时间复杂度O(Nlogk) * 过程: * 1.一直维护一个有k个数的大根堆,这个堆代表目前选出来的k个最小的数 * 在堆里的k个元素中堆顶的元素是最小的k个数 ...

  4. 程序员代码面试指南 IT名企算法与数据结构题目最优解

    原文链接 这是一本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现.针对当前程序员面试缺乏权威题目汇总这一痛点,本书选取将近200道真实出现过的经典代码面试题,帮 ...

  5. 《程序员代码面试指南》第八章 数组和矩阵问题 打印N 个数组整体最大的Top K

    题目 打印N 个数组整体最大的Top K java代码 package com.lizhouwei.chapter8; /** * @Description: 打印N 个数组整体最大的Top K * ...

  6. [程序员代码面试指南]递归和动态规划-最长公共子串问题(DP,LCST)

    问题描述 如题. 例:输入两个字符串 str1="1AB234",str2="1234EF" ,应输出最长公共子串"234". 解题思路 状 ...

  7. [程序员代码面试指南]栈和队列-最大值减去最小值 小于或等于num 的子数组的数量(单调队列)

    题目 给定数组arr和整数num,求数组的子数组中有多少个的满足"最大值减去最小值<=num". 解题思路 分析题目,有结论: 如果数组arr[i...j]满足条件,则它的每 ...

  8. 《程序员代码面试指南》第一章 栈和队列 设计一个有getMin功能的栈

    题目 实现一个特殊的栈,在实现栈的基本功能上,再实现返回栈中最小的元素的操作 要求 1. pop.push.getMin操作时间复杂度都是O(1) 2. 设计的栈类型可以使用现成的栈结构 java代码 ...

  9. 《程序员代码面试指南》第五章 字符串问题 去掉字符串中连续出现k 个0 的子串

    题目 去掉字符串中连续出现k 个0 的子串 java代码 package com.lizhouwei.chapter5; /** * @Description: 去掉字符串中连续出现k 个0 的子串 ...

随机推荐

  1. Nginx 流量和连接数限制

    1.Nginx流量限制 实现流量限制由两个指令 limit_rate 和 limit_rate_after 共同完成: limit_rate 语法:limit_rate rate; 默认值:limit ...

  2. WebApp的自动测试工具: Jenkins

    一.下载并安装(msi)https://jenkins.io/download/thank-you-downloading-windows-installer-stable/ 在安装过程这, 需要从p ...

  3. Vue 可输入可下拉组件的封装

    由于业务需要,需要一个可输入也可下拉的组件,看了iview没有现成的组件用,就自己封装了个小组件~~ 组件input-select.vue代码: <template> <div cl ...

  4. Linux查看版本(centos)

    1.查看内核版本 1.1.uname -a 1.2.cat /proc/version 2.查看发行版本 cat /etc/redhat-release

  5. phoenix 报错:type org.apache.phoenix.schema.types.PhoenixArray is not supported

    今天用phoenix报如下错误: 主要原因: hbase的表中某字段类型是array,phoenix目前不支持此类型 解决方法: 复制替换phoenix包的cursor文件 # Copyright 2 ...

  6. 2018-2019-2 20165205 《网络对抗技术》 Exp6 信息收集与漏洞扫描

    2018-2019-2 20165205 <网络对抗技术> Exp6 信息收集与漏洞扫描 实验目标 掌握信息收集的最基本技能与常用工具的方式 实验内容 各种搜索技巧的应用 DNS IP注册 ...

  7. Win10启动tomcat控制台乱码解决方案

    1.找到${CATALINA_HOME}/conf/logging.properties 2.添加语句:java.util.logging.ConsoleHandler.encoding = GBK ...

  8. MySql CURD操作(数据的增删改查)

    1.增 格式  insert into 表名字 (列名) values(...); 两种方式 1.直接insert into 表名字 values(...);  全部插入 2.insert into ...

  9. mysql脚本转h2

    注意事项:转的时候需要 脚本中不能包含utf8mb4格式

  10. react 和 seamless-immutable

    在 react 中,默认改变组件状态或者属性,是会整个组件全部重新渲染,但是 如果只是修改一个地方,而全部渲染,就会浪费资源,大项目中会造成性能问题 shouldComponentUpdate   s ...