算法通关村第十五关-白银挑战继续海量数据问题

大家好我是苏麟 , 今天继续聊聊海量数据问题 .

理解了前面的题目之后,本文,我们来详细看几道典型的海量数据场景下的查找问题

从40个亿中产生一个不存在的整数

题目要求: 给定一个输入文件,包含40亿个非负整数,请设计一个算法,产生一个不存在该文件中的整数,假设你有1GB的内存来完成这项任务
本题不用写代码,如果能将方法说清楚就很好了,我们接下来一步步分析该如何做

位图存储大数据的原理

假设用哈希表来保存出现过的数,如果 40 亿个数都不同,则哈希表的记录数为 40 亿条,存一个 32 位整数需要 4B,所以最差情况下需要 40 亿*4B=160 亿字节,大约需要16GB 的空间,这是不符合要求的。

40 亿*4B=160 亿字节,大约需要16GB 16GB / 32 = 0.5GB

40 亿/8 字节=5亿字节,大约0.5GB的数组就可以存下40亿个 

如果数据量很大,采用位方式(俗称位图)存储数据是常用的思路,那位图如何存储元素的呢? 我们可以使用 bit map 的方式来表示数出现的情况。具体地说,是申请一个长度为 4 294 967 295 的 bit 类型的数组 bitArr (就是boolean类型),bitArr 上的每个位置只可以表示0或1 状态。8个bit 为 1B,所以长度为 4 294 967 295 的 bit 类型的数组占用 500MB 空间,这就满足题目给定的要求了。

那怎么使用这个 bitArr 数组呢? 就是遍历这 40 亿个无符号数,遇到所有的数时,就把 bitArr 相应位置的值设置为 1。例如,遇到 1000,就把bitArr[1000]设置为 1。

遍历完成后,再依次遍历 bitArr,看看哪个位置上的值没被设置为 1,这个数就不在 40 亿个数中。例如,发现 bitArr[8001]==0,那么 8001 就是没出现过的数,遍历完 bitArr 之后,所有没出现的数就都找出来

位存储的核心是: 我们存储的并不是这40亿个数据本身,而是其对应的位置。这一点明白的话,整个问题就迎刃而解了。

40 亿个非负整数中找到出现两次的数

题目要求:32 位无符号整数的范围是 0~4 294 967 295,现在有 40 亿个无符号整数,可以使用最多1GB的内存,找出所有出现了两次的数。

本题可以看做第一题的进阶问题,这里将出现次数限制在了两次

首先,可以用 bit map 的方式来表示数出现的情况。具体地说,是申请一个长度为4 294 967 295x2 的bit 类型的数组bitArr,用 2 个位置表示一个数出现的词频,1B 占用 8 个bit,所以长度为 4 294 967295x2 的 bit 类型的数组占用 1GB 空间。怎么使用这 bitArr 数组呢? 遍历这 40 亿个无符号数,如果初次遇到 num,就把bitArr[num*2 + 1]和 bitArr[num*2]设置为 01,如果第二次遇到 num,就把bitArr[num*2+1]和bitArr[num*2]设置为 10,如果第=次遇到 num,就把bitArr[num*2+1]和bitArrInum*21设置为11。以后再遇到 num,发现此时 bitArrInum*2+11和 bitArrInum*2]已经被设置为11,就不再做任何设置。遍历完成后,再依次遍历 bitArr,如果发现bitArr[i*2+1]和bitArrli*2]设置为10,那么 i就是出现了两次的数。


这期就到这里 , 下期见!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值