三個問題:
1.給定乙個最多包含40億個隨機排列的32位整數的順序檔案,找出乙個不在檔案中的32位整數(在檔案中至少缺失乙個這樣的數——為什麼?)。在具有足夠記憶體的情況下,如何解決該問題?如果有幾個外部臨時檔案可用,但是僅有幾百位元組的記憶體,又該如何解決該問題?
記憶體足夠的情況下,可以採用位圖法。即設一位圖 至少需要 2^32/8=537mb 記憶體,初始化位圖,每位設定為0。.不斷從檔案中讀入資料,並設定相應的點陣圖資料位1。歷遍點陣圖,資料位為0的即為缺失的整數。
記憶體不足時,可以採用二分查詢法。把40億個隨機數(正整數)分成兩段區間,[0~2^31) 和[2^31~2^32),讀取檔案中的資料,依據資料的首位是0還是1,分別劃分到[0~2^31) 和[2^31~2^32)這兩個區段。只要每個區段的資料個數小於2^32,則必存在缺失的資料。注意,區段中的個數有可能大於2^32,因為資料又能存在重複,書上好像沒有考慮這種情況。如果兩個區段資料個數都小於2^32,則取其小者,若一樣多,則隨機取乙個。若取的是[0~2^31) 區段,則缺失的整數首位必然是0,若在[2^31~2^32)區段,則為1 。如此,總數為n的資料,縮小為 小於n/2個資料的範圍。
如此反覆,則可找到乙個缺失的資料。 時間複雜度o(n) 。
2.將乙個n元一維向量向左旋轉i個位置。例如,當n=8且i=3時,向量abcdefg旋轉為defgabc。簡單的**使用乙個n元的中間向量在n步內完成該工作,你能否僅使用數十個額外位元組的儲存空間,在正比於n的時間內完成向量的旋轉?
咋一想,搞個臨時陣列,東挪挪西挪挪就能搞定了,但必定效率低下啊。
書中說:這個方法有點像精巧的雜技動作,移動a[0]到臨時變數t,然後移動a[i]至a[0],a[2i]至a[i],依次類推(將a中的所有下標對n取模),直至返回到取a[0]中的元素,此時改為從t取值然後終止過程。如果該過程沒有移動全部元素,就從a[1]開始再次進行移動,直到所有的元素都已經移動為止。」
3.給定乙個英語字典,找出其中的所有變位詞集合。例如,「pots」,「stop」,「tops」互為變位詞,因為每乙個單詞都可以通過改變其他單詞中的字母的順序來得到。
「解決這個問題的許多方法都出奇地低效和複雜。任何一種考慮單詞中所有字母的排列的方法都注定了要失敗。而比較所有單詞對的任何方法在我的機器上執行至少要花費一整夜的時間。」
我們獲得的」啊哈!靈機一動「就是標識字典中的每乙個詞,使得在相同變位詞類中的單詞具有相同的標識。然後,將所有具有相同標識的單詞集中在一起。這將原始的變位詞問題簡化為兩個子問題:選擇標識和集中具有相同標識的單詞。
對第乙個問題,我們可以使用基於排序的標識:將單詞中的字母按照字母表順序排列。要解決第二個問題,我們將所有的單詞按照其標識的順序排列。
書中的程式按照三階段的」管道「組織,其中乙個程式的輸出檔案作為下乙個程式的輸入檔案。第乙個程式sign()直接寫在main函式裡來標識單詞,第二個程式排序sort()標識後的檔案,而第三個程式squash()將這些單詞壓縮為每個變位詞類一行的形式。
程式有一些侷限在於要事先輸入單詞的個數,以for迴圈讓輸入停止,而且輸入單詞的長度不能長於20位。
程式設計珠璣第二章
a題給定乙個最多包含40億個隨機排列的32位整數的順序檔案,找出乙個不在檔案中一32位整數。1 在檔案中至少存在這樣乙個數?2 如果有足夠的記憶體,如何處理?3 如果記憶體不足,僅可以用檔案來進行處理,如何處理?答案 1 32位整數,包括 2146473648 2146473647,約42億個整數,...
程式設計珠璣第二章總結
分析 如果記憶體足夠的話,可以採取第一章的點陣圖排序法,以o n 的效率就可以解決。如果記憶體不足的話,但是有幾個外部檔案可以儲存資料,那麼就可以採用二分查詢的思想來解決問題 這裡的思路比較巧妙,它不是通常意義上的二分查詢,但是思維模式很相似.我們可以通過掃瞄輸入檔案,將第一位是0的寫入乙個檔案,將...
程式設計珠璣第二章ABC
問題 找出乙個不在檔案中的32位整數。注意 題目中沒有說,這40億個數是否是含有重複的資料 條件限制 1 如果有足夠的記憶體,如何處理?2 如果記憶體僅有上百位元組 記憶體不足 且 可以用若干外部臨時檔案,如何處理?舉例 比如abcdef 左移三位,則變成defabc 條件限制 空間限制 可用記憶體...