编程珠玑-第二章问题A

来源:互联网 发布:步进电机控制器编程 编辑:程序博客网 时间:2024/05/16 12:41

题目:给定一个包含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 7 6 9 8 10。
根据最高位是0,1可以分为两部分

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,我们选择小的组,进行再分,也是正确的。


总结:

此题用二分的思想,很巧妙在对内存有限制的情况下,能够对大量数据进行处理,巧妙的运用了二分思想,此处的二分是对某一位进行分类,从而达到减小处理数据的大小的目的

原创粉丝点击