来源:http://hxraid.iteye.com/blog/649831

题目:在一个文件中有 10G 个整数,乱序排列,要求找出中位数。内存限制为 2G。只写出思路即可(内存限制为 2G的意思就是,可以使用2G的空间来运行程序,而不考虑这台机器上的其他软件的占用内存)。

分析: 既然要找中位数,很简单就是排序的想法。那么基于字节的桶排序是一个可行的方法 (请见《桶排序 》):

思想:将整形的每1byte作为一个关键字,也就是说一个整形可以拆成4个keys,而且最高位的keys越大,整数越大。如果高位keys相同,则比较次高位的keys。整个比较过程类似于字符串的字典序。

第一步:把10G整数每2G读入一次内存,然后一次遍历这536,870,912个数据。每个数据用位运算">>"取出最高8位(31-24)。这8bits(0-255)最多表示255个桶,那么可以根据8bit的值来确定丢入第几个桶。最后把每个桶写入一个磁盘文件中,同时在内存中统计每个桶内数据的数量,自然这个数量只需要255个整形空间即可。

代价:(1) 10G数据依次读入内存的IO代价(这个是无法避免的,CPU不能直接在磁盘上运算)。(2)在内存中遍历536,870,912个数据,这是一个O(n)的线性时间复杂度。(3)把255个桶写会到255个磁盘文件空间中,这个代价是额外的,也就是多付出一倍的10G数据转移的时间。

第二步:根据内存中255个桶内的数量,计算中位数在第几个桶中。很显然,2,684,354,560个数中位数是第1,342,177,280个。假设前127个桶的数据量相加,发现少于1,342,177,280,把第128个桶数据量加上,大于1,342,177,280。说明,中位数必在磁盘的第128个桶中。而且在这个桶的第1,342,177,280-N(0-127)个数位上。N(0-127)表示前127个桶的数据量之和。然后把第128个文件中的整数读入内存。(平均而言,每个文件的大小估计在10G/128=80M左右,当然也不一定,但是超过2G的可能性很小)。

代价:(1)循环计算255个桶中的数据量累加,需要O(M)的代价,其中m<255。(2)读入一个大概80M左右文件大小的IO代价。

注意,变态的情况下,这个需要读入的第128号文件仍然大于2G,那么整个读入仍然可以按照第一步分批来进行读取。

第三步:继续以内存中的整数的次高8bit进行桶排序(23-16)。过程和第一步相同,也是255个桶。

第四步:一直下去,直到最低字节(7-0bit)的桶排序结束。我相信这个时候完全可以在内存中使用一次快排就可以了。

整个过程的时间复杂度在O(n)的线性级别上(没有任何循环嵌套)。但主要时间消耗在第一步的第二次内存-磁盘数据交换上,即10G数据分255个文件写回磁盘上。一般而言,如果第二步过后,内存可以容纳下存在中位数的某一个文件的话,直接快排就可以了。关于快排的效率,可以看看我博客中的数据《基于比较的内部排序总结》。

 

10G整数文件中寻找中位数或者第K大数的更多相关文章

  1. PJzhang:从js文件中寻找子域名的SubDomainizer

    猫宁!!! 有些专门针对企业客户的网站,可能没有供公开注册的页面,但是在js文件中可能会隐藏他们的注册接口,当然这也是一种安全风险,就像有些后台是一定不能不小心放外网一个道理.   最近看到一篇文章提 ...

  2. 【分步详解】两个有序数组中的中位数和Top K问题

    (这也是一道leetcode的经典题目:<LeetCode>解题笔记:004. Median of Two Sorted Arrays[H] 问题介绍 这是个超级超级经典的分治算法!!这个 ...

  3. O(n)求中位数和第k大数

    解题关键:模板与思路.面试题 #include<cstdio> #include<cstring> #include<algorithm> #include< ...

  4. 两个有序数组中的中位数以及求第k个最小数的值

    解法参考 <[分步详解]两个有序数组中的中位数和Top K问题> https://blog.csdn.net/hk2291976/article/details/51107778 里面求中 ...

  5. 10G个64bit整数,找出中位数

    [10G个64bit整数,找出中位数] 题目:在一个文件中有10G个64bit整数,乱序排列,要求找出中位数.内存限制为2G. 解法:内存限制为2G表面上是限制,实际上是一种提示,在提示我们如何利用2 ...

  6. Eclipse创建第一个Servlet(Dynamic Web Project方式)、第一个Web Fragment Project(web容器向jar中寻找class文件)

    创建第一个Servlet(Dynamic Web Project方式) 注意:无论是以注解的方式还是xml的方式配置一个servlet,servlet的url-pattern一定要以一个"/ ...

  7. C++-模板的声明和实现为何要放在头文件中

    源: http://blog.csdn.net/lqk1985/archive/2008/10/24/3136364.aspx 如何组织编写模板程序 发表日期: 1/21/2003 12:28:58 ...

  8. sort +awk+uniq 统计文件中出现次数最多的前10个单词

    实例cat logt.log|sort -s -t '-' -k1n |awk '{print $1;}'|uniq -c|sort -k1nr|head -100 统计文件中出现次数最多的前10个单 ...

  9. vim学习日志(7):替换、删除文件中的字符

    vim全局替换文件: 语法为 :[addr]s/源字符串/目的字符串/[option] 全局替换命令为::%s/源字符串/目的字符串/g [addr] 表示检索范围,省略时表示当前行. 如:“1,20 ...

随机推荐

  1. 学习图像算法阶段性总结 (附一键修图Demo) 2016.04.19更新demo

    今天特别感慨,自己从决定研究图像处理,势必要做出一键修图算法. 经历了,三个多月的书籍积累,三个多月的算法调整以及优化. 人是一种奇怪的动物,当你做不到的时候,你以为做到了,自己会感觉很爽,很有成就感 ...

  2. NOIP2002字串变换[BFS]

    题目描述 已知有两个字串 A$, B$ 及一组字串变换的规则(至多6个规则): A1$ -> B1$ A2$ -> B2$ 规则的含义为:在 A$中的子串 A1$ 可以变换为 B1$.A2 ...

  3. jQuery学习笔记(一):入门

      jQuery学习笔记(一):入门 一.JQuery是什么 JQuery是什么?始终是萦绕在我心中的一个问题: 借鉴网上同学们的总结,可以从以下几个方面观察. 不使用JQuery时获取DOM文本的操 ...

  4. [No000012]编程中浮点数之什么是科学计数法

    科学记数法 把一个绝对值小于1(或者大于等于10)的实数记为a×10n的形式(其中1≤/a/<10),这种记数法叫做科学记数法. (或者大于等于10)的实数记为a×10^n的形式(其中1≤|a| ...

  5. Android资料之-EditText中的inputType

    在编写有EditText的自定义控件的时候可能会用到EditText的inputType属性,直接在xml里写这个属性的时候是用字符串型的,不过动态设置的时候就变成int型了,InputType里有定 ...

  6. IOS第五课——Gesture and TableView

    这一次我们要学习Gesture.TableView.AlertView三种技术. 一.Gesture 在iOS中,可以使用系统内置的手势识别(GestureRecognizer),也可以创建自己的手势 ...

  7. delphi附带通用控件安装方法:

    附带通用控件安装方法:----------基本安装1.对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;2.对于 ...

  8. 搜索引擎关键词劫持之php篇(源码与分析)

    摘要:其实原理很简单: 搜索引擎关键词劫持的过程实际上就是,修改肉鸡站点(webshell站点)A的首页(希望被搜索引擎收录的页面,一般情况下是首页),使之做出如下判断: if(来访者是蜘蛛){ 输出 ...

  9. 搜索引擎关键词劫持之asp篇

    摘要:关键词劫持(黑帽seo)其实原理很简单:搜索引擎关键词劫持的过程实际上就是,修改肉鸡站点(webshell站点)A的首页(希望被搜索引擎收录的页面,一般情况下是首页),使之做出判断... 黑帽S ...

  10. 【MySql】C#数据库备份与还原

    public static class SQLBackup { /// <summary> /// 执行Cmd命令 /// </summary> /// <param n ...