题目:给定一个包含40亿个随机排列的顺序文件,找到一个不在文件中的32位整数,在有足够内存的情况下应该如何解决该问题?如果有几个外部的临时文件可用,但是仅有几百字节的内存,又该如何解决?
首先40亿=40X10^8 = 4X10^9 ~= 4G,故40亿个随机数,即使数字都不同,也是少于32位的能表示的最大不同数字的个数的,所以必然是缺少数字的。
(1)有足够内存的情况
对于有足够内存的情况,完全可以采用第一章介绍的位图方法,每一位表示第一数字,那2^32需要2^24字节,即16M内存。
(2)仅有几百字节内存和几个稀疏顺序的文件
二分思想:根据二进制数某一位是0还是1,可以分成两部分。
由于只有几百字节的内存和几个稀疏的顺序文件,我们可以先对40亿的数据进行分类,当分成的剩余文件可以用几百字节解决时,我们就可以用位图法了。
先从高位开始,对数据进行分类,根据0,1分成两部分,此时有两种情况:
- 两部分数据个数相同
- 两部分数据个数不同
当数据个数不同时,对数据少的那部分再进行二分,当数据个数相同时,则随机选择一个进行二分。
下面举个例子:
问题的关键是只要找一个数字,那么我们把问题简化一下,给定一个文件,里头最多包含16个4bit的整数,找到一个不在文件中的4bit整数。假设这十个数是
1,2,3,4,5,6,7
8,9,10
那我们接着对8,9,10进行二分,根据次高位是0,1进行分类。
当10个数字是1,2,3,4,5,8,9,10,11,12时,此时分成两部分后都是5个数,随机选择一部分进行二分。
当数字中有重复数字时呢?
1,1,1,1,1,1,1,1,1,2,7,8,8,8
此时14个数时,二分后,一个包含11个数,一个包含3个8,我们选择小的组,进行再分,也是正确的。
总结:
此题用二分的思想,很巧妙在对内存有限制的情况下,能够对大量数据进行处理,巧妙的运用了二分思想,此处的二分是对某一位进行分类,从而达到减小处理数据的大小的目的