作者:vincent-duan,专注 Java,沉迷开源,架构师社区合伙人!

面试题目:如何在10亿个整数中找出前1000个最大的数。

我们知道排序算法有很多:

  1. 冒泡算法:通过两层for循环,外层第一次循环找到数组中最大的元素放置在倒数第一个位置,第二次循环找到第二大的元素放置在倒数第二个位置。。。循环N次就可以找到TopN。
    缺点:冒泡排序内层循环需要大量交换元素。复杂度介于O(n)和O(n^2)之间。

  2. 快速排序:选一个基准元素,每次排序可以将这个基准元素搁置在正确的位置,左边都是比基准小的元素,右边都是比基准大的元素从而将数组分成左右两部分,分而治之。TopN问题也同样如此,选择一个基准元素并通过快速排序将基准元素搁置在正确的位置,如果左边的元素个数小于1000,那么继续从基准右边排序,如果左边元素个数大于1000,那么从基准左边排序,直到基准的位置正好在1000,结束。
    缺点:第一次排序复杂度是O(n),第二次排序复杂度是O(n/2),第三次排序复杂度是O(n/4)....

  3. 文件存储,分而治之:

    将比基准小的元素存储在txt1中,比基准大的文件存储在txt2中,然后通过类似方法二的形式,最后求出TopN。

    缺点:磁盘读取,写入次数过多。

  4. MapReduce:单机内存和性能确实受限,那么我们可以将10亿个分段存储在不同的机器上,每台机器计算各自的TopN,最后汇总。
    缺点:空间换时间。

最优解:小顶堆

在内存中维护一个长度为N的数组,根据堆的性质,每一个节点都比他的左右子节点小,先取出前N个数并构建小顶堆,然后将所有数据与堆顶比较大小,如果比堆顶小就直接丢弃,如果比堆顶大则替换堆顶,并且重新构建这个堆。

构建小顶堆的过程:先要找到最后一个非叶子节点,数组的长度为6,那么最后一个非叶子节点就是:长度/2-1,也就是6/2-1=2,然后下一步就是比较该节点值和它的左右节点值,如果该节点大于其左\右子树的值就交换(意思就是将最小的值放到该节点)。如果该节点不是叶子结点,则递归这一过程,直到这个节点变成叶子节点。

具体执行代码如下:

import java.util.Random;/*** @author vincent* @time 2019-08-07 11:59*/
public class TopN {public static int N = 10;           //Top10public static int LEN = 100000000; //1亿个整数public static int arrs[] =  new int[LEN];public static int result[] = new int[N]; //在内存维护一个长度为N的小顶堆public static int len = result.length;//堆中元素的有效元素 heapSize<=lenpublic static int heapSize = len;public static void main(String[] args) {//生成随机数组for(int i = 0;i<LEN;i++){arrs[i] = new Random().nextInt(999999999);}//构建初始堆for(int i =  0;i<N;i++){result[i] = arrs[i];}//构建小顶堆long start =System.currentTimeMillis();buildMinHeap();for(int i = N;i<LEN;i++){if(arrs[i] > result[0]){result[0] = arrs[i];minHeap(0);}}System.out.println(LEN+"个数,求Top"+N+",耗时"+(System.currentTimeMillis()-start)+"毫秒");print();}/*** 自底向上构建小堆*/public static void buildMinHeap(){int size = len / 2 -1 ; //最后一个非叶子节点for(int i = size;i>=0;i--){minHeap(i);}}/*** i节点为根及子树是一个小堆* @param i*/public static void minHeap(int i){int l = left(i);int r = right(i);int index = i;if(l<heapSize && result[l]< result[index]){index = l;}if(r<heapSize && result[r]< result[index]){index = r;}if(index != i){int t = result[index];result[index] = result[i];result[i] = t;//递归向下构建堆minHeap(index);}}/*** 返回i节点的左孩子* @param i* @return*/public static int left(int i){return 2*i;}/*** 返回i节点的右孩子* @param i* @return*/public static int right(int i){return 2*i+1;}/*** 打印*/public  static void print(){for(int a: result){System.out.print(a+",");}System.out.println();}
}

长按订阅更多精彩▼

如有收获,点个在看,诚挚感谢

如何在10亿个整数中找出前1000个最大的数?相关推荐

  1. 如何在10亿个整数中找出前1000个最大的数(TopN算法)

    面试题目:如何在10亿个整数中找出前1000个最大的数. 我们知道排序算法有很多: 冒泡算法:通过两层for循环,外层第一次循环找到数组中最大的元素放置在倒数第一个位置,第二次循环找到第二大的元素放置 ...

  2. 从十亿个数中找出前1000个最大的数的算法

    10亿个数中找出1000个最大的数的算法思路: 1,先拿出前1000个数字,并排序,找出最小值为 minValue .    2,  然后再依次拿出1000个数字,找出最大值为 tempMaxValu ...

  3. 【面试现场】如何在10亿数中找出前1000大的数

    小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司. 之前小史在BAT三家的面试中已经挂了两家,今天小史去了BAT中的最后一家面试了. 简单的 ...

  4. 如何在 10 亿数中找出前 1000 大的数?

    作者 | channingbreeze 责编 | 胡巍巍 小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司. 之前小史在BAT三家的面试中已 ...

  5. 2.5亿个整数中找出不重复的整数

    问题描述:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数. 思路:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)进行,共 ...

  6. n个数里找出前m个数(或者 从10亿个浮点数中找出最大的1万个)

    转载自:http://blog.csdn.net/winsunxu/article/details/6219376点击打开链接 引子 每年十一月各大IT公司都不约而同.争后恐后地到各大高校进行全国巡回 ...

  7. 在10亿个数中找出前1000个最大的

    在10亿个数中找出前1000个最大的 假设现在有一个文件,里面存放了10亿个整数,需要找出前1000个最大的. 方法: 1.普通排序,部分排序:几乎不可取. 2.分治法:随机选一个数t,然后对整个数组 ...

  8. 一道笔试题:从1亿个整数中找出最大的一万个

    今天看到一篇赖永浩大牛的博客,由一道笔试题目谈算法优化.http://blog.csdn.net/lanphaday/archive/2008/12/19/3547776.aspx. 题目原题是从10 ...

  9. 从10亿个数字中找出最大的前100个数

    先拿10000个数建堆,然后一次添加剩余元素,如果大于堆顶的数(10000中最小的),将这个数替换堆顶,并调整结构使之仍然是一个最小堆,这样,遍历完后,堆中的10000个数就是所需的最大的10000个 ...

最新文章

  1. 函数实现十进制转二进制
  2. UNIX再学习 -- 环境变量
  3. Dubbo—dubbo admin安装
  4. ++i与i++的根本性区别(两个代码对比搞定)
  5. 艾创机器人_世界教育机器人大赛 2019赛季世界锦标赛落幕曲靖代表队获多个奖项...
  6. 【转】3.4(译)构建Async同步基元,Part 4 AsyncBarrier
  7. c语言结构体调用成员函数,c语言结构体函数调用参数如何设置
  8. 用excel打开txt文件
  9. 渗透之——SQLMap参数说明
  10. 数据库面试考题一览(全面覆盖)
  11. 电子签名就是数字签名吗?
  12. 苹果手机刷机显示无法联系软件更新服务器,为什么苹果手机无法自动更新软件怎么办...
  13. 音频转换成文字的方法你知道吗?操作非常简单
  14. 6763个gb2312汉字笔画分析
  15. vue-element-admin实现login和logout
  16. 基于二轴云台目标跟踪系统设计
  17. 安利一款功能强大,简单好用的录屏软件!
  18. .theanorc文件配置问题——AbstractConv2d theano optimization failed
  19. 小程序直播如何去做-西安青云在线
  20. 文件改名:如何将文件夹进行批量翻译重命名

热门文章

  1. 带修莫队 ---- P1903 [国家集训队]数颜色 / 维护队列 带修莫队模板
  2. python 工业自动化 人工智能_浅谈人工智能神经网络与工业自动化
  3. 解题报告:luogu P1688 新单词接龙问题【trie树、dfs、DP递推】
  4. 计算机一级b类试题及答案,计算机一级b类试题及答案
  5. 104.二叉树的最大深度
  6. python文件读写_python文件操作-读写删除复制总结
  7. 怎么安装linux系统 硬盘,如何实现硬盘安装linux系统
  8. Spring之HelloWorld再起
  9. LeetCode-106-Construct Binary Tree from Inorder and Postorder Traversal
  10. 【leetcode】7.反转整数(Reverse Integer)