找出一个不在文件中的整数 编程珠玑

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

编程珠玑》第2章第一节提出的三个问题中,第一个问题是这样的:
问题一:给定一个最多包含40亿个随机排列的整数的顺序文件,找出一个不在文件中的32位整数。

在考虑内存受限(只有几百个字节)的情况,书中给出了很好的解法,即使用二分搜索,每次将范围限定在数量较少的那一半空间中,这样顶多 logN 次搜索之后就可以限定所求整数(N为整数个数)。

如果不写中间文件,即每次都读所有数据,那么Read的数据量大约为 N * logN。

如果允许在二分搜索的过程中将二分所得的两部分数据写入两个临时文件中,下次搜索时只在其中之一的文件中读取,那么Read的数据量约为(N + N/2 + N/4 + ...)< 2N,Write的数据量同样 < 2N。

我曾经考虑将二路划分改进为多路划分,即将所有内存都利用上。假设内存最多可以当做 M 个计数器,则每次可以将搜索范围缩小为原来的 1/M,这样总的搜索次数小于 logMN,本以为这样会快很多,但实际上Read和Write次数仍然在 N 以上,连一倍都快不了!这样看来,简单的二分搜索的性价比已经很高了。
具体做时,我们可以根据最后一位0或1将数分成两组。(最好是二进制的最后一位的分类 或根据该数是不是偶数进行分组:判断一个数是不是偶数 可用a&1==0)
-------------

后面的习题2中,也给出了一个与之对应的类似的问题:

问题二:给定一个包含43亿个随机排列的整数的顺序文件,找出一个出现至少两次的32位整数。

实际上这个问题本身具有其特殊性。因为既然包含 43 亿个整数,大于32位整数所能表示的不同整数的个数
232,根据鸽笼原理,至少会有一个整数出现两次。同样考虑二分的方法,采用已知包含一个出现至少两次的整数的一个连续整数序列作为范围,统计范围中间点之上和之下的元素个数,其中较多那部分必然仍然包含一个出现至少两次的整数。如此递归查找下去,在 logN 次之后就能找到这个数。计算复杂度与问题一类似。

-------------

但是问题二稍作改变,整数个数不是43亿个,而是40亿个,那么问题的难度就显然不同了。
问题三:给定一个包含40亿个随机排列的整数的顺序文件,找出一个出现至少两次的32位整数。

原文地址:https://www.cnblogs.com/corecible/p/1750291.html