标签:open params href figure comm ram 为什么 文件重命名 line
给定一个最多包含40亿个随机排列的32位的顺序整数的顺序文件,找出一个不在文件中的32位整数。(在文件中至少确实一个这样的数-为什么?)。在具有足够内存的情况下,如何解决该问题?如果有几个外部的“临时”文件可用,但是仅有几百字节的内存,又该如何解决该问题?
这仍然是《编程珠玑》中的一个问题。前面我们曾经提到过《位图法》,我们使用位图法解决了这个问题。32位整型最多有4294967296个整数,而很显然40亿个数中必然会至少缺一个。我们同样也可以尝试使用位图法解决该问题,使用536 870 912个字节,约512M内存存储这40亿整数,存在该整数的位置1,最后遍历比特位,输出第一个比特位为0的位置即可。那如果仅借助几个“临时”文件,使用几百字节的内存的情况下该如何处理呢?
能否使用二分搜索呢?这40亿个整数是随机排列的,因此普通的二分搜索不能找到那个不存在的数。但是我们可以基于二分搜索的思想。
一个整数有32位,我们按照每个比特位是0还是1,将要查找的数据范围一分为二。从最高比特位开始:
这里需要做一些解释:
由于32位的整型数据量太多,不便说明,我们用一个4比特的数据对上面的思路再做一个说明。4比特最多有16个数。
假设有以下源数据:
|
|
对应二进制形式如下(负数在内存中以补码形式存储):
|
|
1.处理第1比特位被分为两部分数据,分别为:
|
|
|
|
可以看到,第一比特位为1的数为5个,比比特位为0的数要少,因此选择比特位为1的数,继续处理。且第一比特位,获得1.
3.处理第2比特位仍然分为两部分数据,分别为:
|
|
|
|
可以看到,第一比特位为1的数为3个,比比特位为0的数要多,因此选择比特位为0的数,继续处理。且第二比特位,获得0。
2.处理第3比特位仍然被分为两部分数据,分别为:
|
|
|
|
明显看到第三比特位为0的数没有,因此选择比特位0,获得0。至此,已经没有必要继续查找了。
我们最终得到了前三个比特位100,因此不存在于这些数中至少有1000,1001,即-8,-7。
C语言实现:
|
|
代码说明:
利用脚本产生了约2000万个整数:
|
|
编译运行:
|
|
程序的主要时间花在了读写文件,且占用内存极小。
本文从一个特别的角度用最常见的二分搜索解决了该问题,最多拆分32次,便可从中找到不存在的整数。你有什么更好的思路或优化点,欢迎留言。
标签:open params href figure comm ram 为什么 文件重命名 line
原文地址:https://www.cnblogs.com/wangziqiang123/p/11618442.html