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


    题目:

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

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

    内存只有 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亿,该数在大部分。
    以此循环下去。

     

     

     

     

     

     

     

     

     


     

  • 相关阅读:
    计算机科学引论笔记
    Bootstrap实战 瀑布流布局
    前端性能和加载体验优化实践(附:PWA、离线包、内存优化、预渲染)
    Promise + Async&Await + Array.reduce + 函数递归 解决网络/接口请求的依次/排队不间断间隔访问
    webfunny前端监控新产品发布:点位系统上线,简单6步操作
    Java 全栈知识体系(2021 PDF 版本)
    Java 面试题及答案整理(2021最新版)持续更新中~~~
    python相关常见安装问题
    获取某一个数的2进制位数以及bitmask
    centos7下利用qemu搭建arm模拟器
  • 原文地址:https://www.cnblogs.com/cherryljr/p/7532364.html
Copyright © 2020-2023  润新知