大数据中找上中位数的方法

题目:数组

40亿 大整数,组成了一个大文件。
想找到其中的 上中位数该怎么办?
内存:10MB,怎么办?
内存:20K,怎么办?
内存:有限几个字符,怎么办?
条件:按行读取文件,读取操做不占用内存。
大数据

应该具有的能力:
2^k = ? 应该都可以熟记,达到反射性反应的程度。
字节数 对应计算机中的 容量(T, G, M, K)spa

内存只有 10MB 的状况
接下来咱们来解题:
看到大数据容量限制的,首先想到的是从范围入手。
1. 数据是 有符号? / 无符号?
2. 咱们知道一个 4字节的无符号整数 范围为:0~42亿
那么咱们能够用一个 unsigned int 来表示一个数出现的次数
(一个数最多出现 40亿 次,故可以表示,不会溢出)
3. 咱们来计算 10MB 内存能够存几个 unsigned int 的数。 => 250万
所以咱们知道 10MB 内存足够咱们在 250W 范围内进行 精细的词频统计(每一个数出现几回)
4. 0~42亿 内总共有 1680个 250W 范围的段。所以咱们将 42亿 的范围按照 250W 进行分段。([0, 250w), [250w,500w)...)
创建一个 1680 的数组,遍历大文件一次,来统计每一个段中出现数的个数。
count[i] 就表示在第 i 段的 连续的250W 的范围内,出现了多少个数。
好比:一个数字值为10亿,那么它应该就在 count[400] 这个段中,那么进行操做 count[400]++ 便可。
5. 对 count 进行累加,直到 sum >= 20亿。这样咱们就能肯定第 20亿 个数是来自哪一个范围的。
6. 释放该数组,再次遍历大文件,利用 10MB 的空间对该范围内的数进行 精细的词频统计。这样便可以找到中位数了。
因而可知,以上作法是借用了 桶排序 的思想。排序

总结:
1. 利用限制的范围计算出咱们可以在多大的范围内进行 精细的词频统计。
2. 利用 精细的范围 对总体范围进行划分,创建一个粗略的统计数组。
3. 遍历大文件,找出中位数粗略的范围。
4. 对该粗略的范围进行精细的统计。内存

内存只有 20K 的状况:
咱们依然用上面的方法来分析:
20K 的内存能够支持 5000范围大小 的精细词频统计。
而后咱们用 40亿 / 5000 => 发现该数值已经怨愿你大于 5000 了,咱们根本没法进行粗略范围的统计。
因而,咱们不妨逆过来思考。
直接从 粗略的范围 出发进行统计。将其分红 5000 份。
咱们依然可以得知 中位数 是在哪一个部分。而后看该范围可否被精细统计。
若不能一直循环下去。变量

内存只有 有限几个字符 的状况(好比就8个字节,两个变量):
采用二分的方法。最多二分 32 次,即须要读 32 次文件。
1. 首先对 0~42 亿二分(注意是对整个范围进行二分),用一个变量 k 记下当前的值是多少。
遍历文件一边遍,计算当前小于当前值得数据个数 n。
2. 若 n < 21亿,该数在小半部分。若 n > 21亿,该数在大部分。
以此循环下去。循环

相关文章
相关标签/搜索