100亿数据的中位数内存够和不够

文章目录


1、题目描述
给定100亿个无符号的乱序的整数序列,如何求出这100亿个数的中位数(中位数指的是排序后最中间那个数)。

2、解题思路一
一个无符号整数的大小为4B,则100亿个数的大小为40GB,如果内存够大的话可以对这100亿个数加载到内存中,然后使用堆排序或者快速排序进行排序,取出中位数即可。使用快排时,每次划分之后只需要比较枢纽值的索引和50亿比较,然后只对两个划分中的一个进行递归排序即可,而不用整体进行排序。使用堆排时,建立堆之后,需要进行50亿次的调整即可。

3、解题思路二
中位数问题可以看做一个统计问题,而不是排序问题,无符号整数大小为4B,则能表示的数的范围为为0 ~ 2^32 - 1(40亿),则可以用一个2^32(4GB)大小的数组(也叫做桶)来保存100亿个数中每个无符号数出现的次数。遍历这100亿个数,当元素值等于桶元素索引时,桶元素的值加1。当统计完100亿个数以后,则从索引为0的值开始累加桶的元素值,当累加值等于50亿时,这个值对应的索引为中位数。时间复杂度为O(n)。

4、解题思路三
如果内存的大小小于4GB时(假设内存为512M),这时怎么办呢?解决方案为使用区间的桶排序,解题思路如下:

(1)如果只有512M的内存,则512M内存可以装2^(9 + 10 + 10) = 536,870,912个无符整数,约为5亿左右,接着把无符号整数的范围040亿划分为每10个数一个区间,也就有4亿个区间,划分后第一个区间09,第二个区间10~19,…在内存中使用4亿个数来保存100亿个数中落在每个区间的整数个数。此时内存中还可以存放1亿个数,分100次把100亿个数加载到内存,每次加载1亿个,统计落到每个区间的整数个数。

(2)第一步完成统计之后,可以知道落到4亿个区间中每个区间的整数个数,然后从最小区间向最大区间开始累加,当累加的数达到50亿时,记住这个区间起点位置和终点位置(终点 - 起点 + 1 = 10)和没有加这个区间统计个数时的整数个数。

(3)知道第50亿个数所落在的区间起点和终点位置后,接着对区间的每个数设置一个桶(这里总共为10个桶),用来统计每个数的元素个数。接着对100亿个数分20批次进行遍历,每次加载到内存5亿个数。

(4)统计完成之后就可以知道落到区间内的每个元素个数,接着对区间的统计个数进行累加,当这个累加值加上(2)中保存的没有加上该区间的整数个数等于50亿时,该数对应的索引就位中位数。

总结:整个过程需要遍历100亿个数两次,第一次确定第50亿个数所落在的索引区间,第二次确定第50亿个数所落在的索引。区间大小是一个可以优化的值,优化之后可以使得I/O的次数最少。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值