【数据结构与算法】海量数据解决方案 bitmap

来源:互联网 发布:php 求数组中最大值 编辑:程序博客网 时间:2024/06/11 18:26

新浪的一道笔试题,后来上网get到新的姿势。

首先是一个常识,1亿是10的8次方,1G大概是10的9次方,2的10次方是1024,约等于10的3次方,所以10亿大概是1G。

问题:有10亿个无符号整数,问有没有办法在内存不超过1GB前提下,找出所有的只出现了一次的数。

这个是一个计数的题目,常规的做法是用一个map存下每一个数字的次数,但是这个会超过内存限制,建简单的计算下:

一个数占4个Byte,10亿个数如果全部不相同,那么占4*10^9也就是4GB空间,这还只是map的key空间,加上count会更大,所以该方案不可行。

下面先看bitmap的概念。

一个int数字是32位,那么这32位可以表示32个数字。比如说,从低位开始,0位表示0,1位表示1,2位表示2,。。。,31位表示31,所以int的32位可以表示总共32个数字。那如果超过32个数字呢?多用几个int就行了,通常我们可以用一个int数组,比方说用第一个int表示了0-31的数字,那么32可以用第二个int的低0位表示。

假设要表示N个数字,那么需要N/32个。如何定位到一个数n对应的bitmap数组索引呢?n/32,如何定位到数n在数组内的bit呢?n%32。

如果要表示所有的32位数字,需要多少空间?

总共需要表示2^32个数字,需要2^32 / 32个int,也就是2^27个int,也就是2^29个Byte的空间,也就是512MB空间,所以我们可以用512MB的空间表示出所有的32位int数字。只用了1/32的空间。

这就是bitmap的思路,用一个int表示了32个数字,是一个海量数字节省内存的方法,其关键是定义一个从int到bit的映射。


那么再回到上面的题目,我们需要得到所有只出现了一次的数字,前面我们用512MB的空间表示了所有的数字,每一个数字分配了一个bit,所以每一个数字只可以对应两个状态,而这里,实际上是三个状态:没有出现,出现一次,出现多次。所以我们需要为每一个数字分配两个bit,那么一个int可以只表示16个数字了,所需要的空间为原来的2倍,即1GB,正好满足要求。