《編程珠璣》第二章2.1的三個問題中,有個問題是這樣的:
給定一個最多包含40億個隨機排列的32位整數的順序文件,找出一個不在文件中的32位整數(在文件中至少缺失一個這樣的數——爲什麼?)。
1、如果有足夠的內存,如何處理?
2、如果內存不足,僅可以用幾個外部的臨時文件來進行處理,如何處理?
主要關注第二個問題,在僅有幾百個字節的內存下,如何藉助外部的“臨時”文件解決該問題?
第二章主要對於二分法進行研究,故使用二分法,給了我們一個很好的答案。
寫的很清楚了,從第一位開始探測,根據是0或1進行分組,對包含的整數個數不大於N/2的序列繼續進行探測,只要搜索到某個位數時,有個分組爲的整數個數爲0,那麼便成功找到缺少的數。
考慮一個極端情況,以對3位的整數進行查找爲例。
有如下8個3位的整數:0、1、2、3、4、4、6、7。
以二進制表示是:
000
001
010
011
100
100
110
111
要探測該序列,在探測第一位時,發現分組個數一樣,故無法進行捨棄;在探測第二位時仍需探測全部的8個數,而探測第二位時,0與1的個數仍相同,也無法捨棄;最終只能通過末位進行判定,而對末位,即使知道了有3個是0,5個是1,缺少的是以0結尾的數,也無法確切的知道整個整數是什麼,因爲第1、2位都無法確定應是1或0.
之所以會有這種情況,是因爲在處理倒數第N位時,
1、 有大於等於2的N次方個數
2、 根據0或1進行分組時,分組包含的數字個數一樣,且有個分組包含了所有的01序列組合。(如上面的倒數第三位爲0的序列)。
於是,導致無法進行縮減,若運用作者提供的方法,則很有可能會出現錯誤。
回到原題,若判定的後N位數,恰好是這樣的情況,該當如何?
解決:若有這種情況,壓根不會進入這個一類中探測。可以模擬一個4位數的數列嘗試。
如果一個序列的後N位至少含2的N次方個不相同的數,那麼倒數第n+1位(不論是0或1)的這一類至少有2的n次方個整數,則定不會選擇該類繼續(若選擇該類,說明另一類含有的整數數量不小於他,那麼總數一定大於2*2的n次方個,不合題意),故選擇到的一類,定是缺了某個數的一類。