海量数据中找出中位数或者第N大(小)数————桶的思想解决方案
来源:互联网 发布:哪种编程语言好 编辑:程序博客网 时间:2024/05/19 02:23
这几天被打击的不行,心情还是依然的低落,还是去面试了,2次都遇到了这同样的问题,都是基于这个思想解决的。下面以寻找中位数位为例,说明此方法。
题目:在一个文件中有 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)的桶排序结束。我相信这个时候完全可以在内存中使用一次快排就可以了。
- 海量数据中找出中位数或者第N大(小)数————桶的思想解决方案
- 海量数据中找出中位数
- BFPTR算法(中位数的中位数算法)求n个数中第k大的数
- 从n个元素中找出第K小的数 利用快排的思想来实现
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 从海量数据中找出中位数
- 面试题—— 找出一个无序整型数组中第k大的数。
- 寻找无序数组中第k大的数——快排思想
- 利用快速排序思想找出数组中第K大的数
- 一题多解(五) —— topK(数组中第 k 大/小的数)
- 找出两个含有相同元素个数的递增数列中第n小的数
- Java中Executor接口的说明和使用
- Zookeeper集群安装小结
- MFC入门
- LINQ 速查
- ESQL 速查
- 海量数据中找出中位数或者第N大(小)数————桶的思想解决方案
- C#中Split用法
- MFC中CALLBACK函数 和WINAPI函数的区别
- shell之“>/dev/null 2>&1”
- WPF 控件模板 Simple Styles.xaml
- addFieldToFilter 与 addAttributeToFilter使用总结
- C# 强制关闭当前程序进程
- 为何WP了不起,市场却争不过Android
- OpenGL源代码之基本框架