一道笔试题:从1亿个整数中找出最大的一万个
来源:互联网 发布:js position属性 编辑:程序博客网 时间:2024/06/06 13:22
今天看到一篇赖永浩大牛的博客,由一道笔试题目谈算法优化。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亿个整数中找出最大的1万个(上)
- 也论从1亿个整数中找出最大的1万个(下)
- 从100亿个整数中找出最大/最小的1000个整数
- 满大街都是这种烂题目------从100亿个整数中找出最大的1000个整数
- 面试-从10亿个浮点数中找出最大的1万个
- [转]从10亿个浮点数中找出最大的1万个
- 面试-从10亿个浮点数中找出最大的1万个
- 从10亿个浮点数中找出最大的1万个
- 找出N个整数中最大的K个数
- 找出N个整数中最大的K个数
- 找出N个整数中最大的K个数
- 找出N个整数中最大的K个数
- 找出N个整数中最大的K个数
- 找出N个整数中最大的K个数python
- 【EMC笔试题】N个整数中找出三个数,使其和的绝对值最小
- 考察最大元素:从n个整数找出最大者
- 运用bitmap解决一道海量数据处理面试题:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
- 一本好书
- Shell学习笔记
- 我要做程序员啦~~
- 用Delphi写的最简单的winsock程序
- WebService学习笔记5——AXIS2基础
- 一道笔试题:从1亿个整数中找出最大的一万个
- 黑客帝国字母雨C++源码
- REST与SOAP样式Web 服务的区别
- 必须和/同一分区,不能挂载到其他分区的目录
- Win7中IIS7安装配置
- IIS中打开网站要输入用户名和密码
- 两块钱的感恩
- 从零开始学算法:十种排序算法介绍(上)
- Web服务与面向服务的体系结构