海量数据

编程珠玑第二章开始提出了三个问题,其中第一个问题是这样的:一个顺序文件至多包括40亿个32位的整数,这些数是无序的,找出一个不在该文件中的32位整数。(可能有数字是不在该文件中的,因为2^32总共包括了42+亿个数,因此肯定有整数是不在该文件中的,这是鸽巢原理吧?)

据说这是腾讯的一道面试题,大概描述如下:

问题描述:

问题的描述大概就是这样了。

刚看到这个题目就想到了bitmap,很适合使用,下面简单说明下。

1、bitmap方法

如果问题对于内存没有要求,可以采用bitmap的方法。对这40亿个数进行bitmap,如果某个数在文件中,那么将其bitmap设置为1,如果不在则设为0;这样操作后在遍历文件对应的bitmap,遇到某一位为0,则说明这个数是不在文件中的,输出就可以了。

这样的情况下总共需要至多:40亿/(8*1024*1024)M,这个大约是500m。如果内存空间够的话就可以采用这种方法。但如果内存有严格限制,这种方法就不可取了。

2、二分法

这里利用了二分的巧妙思想:因为二进制中每一位要么是0要么是1,因此可以根据数据的某一位来分,该位为1的在分配在一组,该位为0的分配在另一组。这里的二分法就是采用了这种思想。

对这40亿数来说,进行如下操作:从最高位到最低位(反过来也可以)按照上面的思想进行分组,例如对于最高位为1的分在一组,最高位为0的分在另一组,这样40亿数据就被分配成了两组了,下面考察这两组数据。

经过上次划分后两组数据可能有下面的情况:

a、两组数据包含的数是相等的,即都是20亿。

b、两组数据包含的数是不等的,一个大一个小。

对于a来说,因为两组数有相同的个数,那么我们可以判断这两组数中都缺少了全体数(2^32个)中的某一个或者多个数。

对于b来说,我们可以肯定是小的那部分数据肯定缺少了某一个或者多个数,而多的那一部分是不确定的,当然也可以判断出来。(通过跟2^32/2=2^31比较)

对于情况a来说,我们可以任选一组数继续进行二分操作;对于情况b来说,我们选择数据量小的那部分数据继续进行二分操作,这样不断的进行下去,就可以找到某个不在40亿数中的数了。

这里很巧妙的利用了二分法,而且与平常使用的不太相同。这里是根据一个数的某一位来将数据分配到不同的组中。

上面就是这个问题的大概思路:用位图法很直接,但占用内存量会大点;利用二分法比较巧妙,不太容易想到。

 

编程珠玑课后提出了另外一个问题:

找出43亿32位整数中至少重复两次的数?首先肯定是有数是重复的,因为2^32总共的数据是42亿多,不到43亿,根据鸽巢原理,肯定是有重复的。如何操作?

当然,有了前面的介绍很容易想到继续采用二分法,思路完全一样。

其实当内存空间没有要求的话,用位图法也是可以的,因为题目只是要找到一个至少重复两次的数就ok了,这样使用位图在遍历数据的时候发现重复的话就可以结束了,时间复杂度是线性的,当然空间复杂度是大点。

 

在网上又看到了这样一个问题:

给定一个包含40亿个随机排列的整数的顺序文件,找出一个出现至少两次的32位整数。这个问题的难道比上面的应该都高。

这里首先想到bitmap,是可以操作的。

还有其他更高效的算法了吗?应该有吧。hash?其实感觉bitmap就是hash的一个特例,bitmap是将数据hash到了位置上。

==============================华丽的分割线============================

上面是关于编程珠玑第二章的问题A和课后类似题目的解答,其实这里面最重要的思想还是bitmap,而且bitmap的应用十分的广泛,简单总结下:

1、bitmap可以用于海量数据的排序

这种情况可能有一些要求,比如数据尽量不重复。如果数据不重复的话,而且空间没有要求,那么bitmap是很高效的。当然如果数据有重复,但能知道重复至多不超过多少,也是可以的。例如数据至多重复10次,那么可以用4位来表示一个数据,这样还是比4个字节(一般整数是4个字节)的空间减少了很多。

2、bitmap用于查找缺少的数据、重复的数据

这个问题在上面的描述中都有体现了,40亿数据中不包含那个32位的整数;43亿数据中哪个数是至少重复两次的?

3、其他应用

后面找找看,再补充

==============================华丽的分割线============================

从上面以及前面的分析可以知道,bitmap是很赞的一种思想,也是很值得应用和掌握的。当然它也有一些限制条件。例如,当内存使用有限制,而且数据量比较大的时候,bitmap可能也是不行的,这样的情况下就可以考虑上面的二分法了。

 

这里总结了bitmap和二分法的一些应用,主要来自编程珠玑和网络,具体参考的一些内容包括:

1、编程珠玑(大力推荐这本书,大力推荐英文版,中文版翻译的很烂)

2、关键字:海量数据处理

3、关键字:bitmap

4、网络资料:

http://kb.cnblogs.com/page/95701/   

http://hi.baidu.com/zhizhesky/blog/item/d4c9d6c45a74d2c138db493b.html

http://bbs.gimoo.net/thread/139984-1.html

http://archive.cnblogs.com/a/1868899/

http://hi.baidu.com/diwayou/blog/category/%B1%E0%B3%CC%D6%E9%E7%E1

http://www.cntxk.com/CataNews/68/info11048.html

http://blog.csdn.net/shuqin1984/archive/2011/02/24/6204224.aspx

http://hi.baidu.com/wentaotao/blog/item/4f73f9c7dcc2630b9d163db8.html

http://hi.baidu.com/%F1%FB%D7%F3%D1%D4/blog/item/b687f76c415bc0f142169472.html

http://blog.csdn.net/shuqin1984/archive/2011/02/24/6204224.aspx

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值