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

题目原题是从10亿个浮点数中找出最大的一万个,赖的文章主要是讲如何去优化算法,并不是侧重在这道题目,所以对其进行了简化。

题目:从1亿个整数中找出最大的一万个。

 

赖永浩的解法:

基本思想是维持一个数组记录当前最大的一万个数,每来一个新数将其与数组中最小的数比较、替换。该数组初始先排序,第一次交换后数组就分成了两部分,后面9999个有序,最小的是1号元素,前面的部分无序。找当前最小元素需要遍历无序部分和有序部分的第一个。当无序部分长度达到600时,就对无序部分排序,然后两部分合并重新得到完整有序数组。

(开始我觉得600这数字太大,后来试验果然这样最优,之所以看起来比较大是因为,每次合并也需要时间,所以不能频繁排序)

我的想法一:用堆

这也是经典的题目了,一般来说用堆来做。这两种解法其实一样,只是找最小值时候不同罢了。我感觉赖的解法不如堆高效,就试了下,确实堆要快很多。在我的机子上赖的解法要1000ms,用堆只要550ms。(破机器,我开始以为我代码也的不好,后来拷赖的代码也是比他的时间慢几倍)

后来发现其中250ms用在一亿次的循环体上(原因是数据太简单了,具体见下文),所以用了循环展开,展开5次,时间变成了390ms。

我的想法二:

找第K个数有中位数之中位数法(传说中的来自圣经的算法第五名:BFPRT)。这种方法K很大的时候很快,这里找一亿个数中的第一万个,可以修改一下。将一亿个数100个一组共100W组,每组找出最大的,然后从这100W个数中找出最大的1W个,整体一亿个数最大的1W个就在对应的1W组共计100W个数中。

我的想法三:

可以建立65536个计数器,记录每个数据段有多少个数,countArr[ SourceArr[i]>>16 ]++;。一遍遍历之后就可以知道第一万个数在哪个数据段的第多少个数。然后整体进行再进行一次遍历,这次countArr[ SourceArr[i] & 0xffff]++,另外SourceArr[i]所在数据段整体都在前1万的直接输出。

这个方法缺点是要两次遍历,如果数据量太大不能一次读入内存,就需要两次磁盘读取,这是坚决不能接受的。上一种方法中也可能要读两次,但第二次只需要读一小部分数据。

有人提出用4G/8的bitmap,直接找出前1万个,这不可行,因为数字可能有重复,这样只能找出一个范围,仍要二次遍历。

方法的比较

在写后面的解法时无意中发现一个一亿的空循环就要250ms!堆竟然如此快?检查了下,因为数据生成太简单了SourceArr[i] = (rand()<<16) + rand()循环一亿次,产生的随机数有一点不随机的地方在于分布太平均了,导致总的替换次数仅为10W次左右。在这种情况下维持一个一万的最大数组是非常明智的选择,不管是用堆还是赖的解法。(极端的例子,简单地直接随机生成1W个0到9之间的数,找出其中第1K小的,则不是0就是1,只用统计下0的个数就知道了)实际的数据不一定是这样,换个复杂点的随机数生成就不一样了,而后面两种方法都不太受数据分布的影响。所以要找最优的解法要根据实际数据的情况。

回归原问题:10亿个浮点数中找出最大的一万个

浮点数就不能采用最后一种方法了,其它几种方法仍然可行。不过最佳答案估计还是分组,每组100W,找出最大的1W,然后各组合并。这样还可以做并行处理,很符合MapReduce。

一道笔试题:从1亿个整数中找出最大的一万个相关推荐

  1. 如何在10亿个整数中找出前1000个最大的数?

    作者:vincent-duan,专注 Java,沉迷开源,架构师社区合伙人! 面试题目:如何在10亿个整数中找出前1000个最大的数. 我们知道排序算法有很多: 冒泡算法:通过两层for循环,外层第一 ...

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

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

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

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

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

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

  5. 在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数

    方案1:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)进行,共需内存2^32 * 2 bit=1 GB内存,还可以接受.然后扫描这2.5亿个整数 ...

  6. 大数据面试题——如何在大量的数据中找出不重复的数

    问题描述: 在2.5亿个整数中找出不重复的数,注意,内存不足以容纳2.5亿个整数. 分析解读: 方法一:分治法 采用hash的方法,把这2.5亿个数划分到更小的文件中,从而保证每个文件的大小不超过可用 ...

  7. 【C语言练习】四个整数中找出最大的一个

    <啊哈C语言>这本书上的练习题: 从键盘任意读入四个整数,让计算机从中找出最大的一个. #include <stdio.h> #include <stdlib.h> ...

  8. 从一亿个数中找出最大的一万个数或最小的一万个数

    1 从一亿个数中找出最大的一万个数:(前10000个元素构建最小堆,后续元素与根节点比较,大于放进去,小于或等于不处理) 用前一万个数初始化一个固定大小为10000的最小堆,这时根节点是这10000个 ...

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

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

最新文章

  1. 深度学习tensorflow框架的会话
  2. MyEclipse 14 设置文件特定的打开方式
  3. 基于php的选课系统设计(含源文件)
  4. python 文件指针及文件覆盖
  5. 20161120-安全测试
  6. 最新席瓦莱恩服务器人口比例,魔兽世界怀旧服:2021年3月最新人口比例数据
  7. 如何回答「你的优势和劣势是什么」?【面试核心问题6】
  8. 专访贤华老师:阐释护肤真谛
  9. CSS a:hover
  10. 混音合成效果器:Cradle The God Particle for Mac
  11. 干货全拿走-用Excel制作小市值轮动价值投资选股器
  12. grub.cfg使用说明
  13. nginx基础学习记录
  14. 大专考试计算机英语题目,专科英语入学考试题
  15. 《底层逻辑-半秒钟看透问题本质》读后感
  16. 乐鑫Esp32学习之旅⑦ esp32上利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。(附带Demo)
  17. Python面向对象,从农药到吃鸡 bilibili视频笔记
  18. dotNetFx40_Client_x86_x64和dotNetFx40_Full_x86_x64这两个有什么区别?两个都要安装还是安装其中一个?...
  19. 3D游戏引擎剖析【较全面】
  20. vmware esxi 6-7 全套资源分享(定期更新)

热门文章

  1. PM_01 信息化和信息系统
  2. 从头开始学算法:考研机试题练习(C/C++)–STL使用
  3. android pak文件_Android 获取手机中已安装apk文件信息
  4. 硅谷公司年薪报告:谷歌年薪最高 收入中位数24.7万美元
  5. lpc1778/lpc1788写内部EEPROM的一个注意点
  6. 【转载】凹凸贴图、法线贴图、置换贴图
  7. T285913 英桀们的战役
  8. servlet的多种注册方式
  9. 再来 20 个免费的 Bootstrap 的后台管理模板
  10. 使用QT简单实现一个画图工具