尋找丟失的數字(一)


這是一個有趣的面試題。

有一個袋子,里面放有1, 2, 3, ... , 100, 共100個整數,且每個數字只出現一次。現在由於袋子破了個洞,造成其中一個數字丟失了。請找出丟失的數字。

很容易想到的方法是:我們可以用減法,1 + 2 + ... + 100的和減去袋子中所有數的和,其差就是丟失的那個數字。1 + 2 + ... + 100

可以由等差數列公式100 * (1 + 100) / 2 = 5050算出,我們只需要遍歷一次袋子中的數字即可。

把這道題推廣到一般情況:設 π 是{1, 2, ... , n}的一個全排列,π-1 是 π 中丟失了一個數字后的序列。找出序列 π-1 中缺失的數字。

當 n 比較小時,我們仍可以用上面的方法,但是當 n 很大時,上面的方法就會有溢出的問題。雖然我們可以合理安排加減法的順序以避

免溢出,但實際上我們有更巧妙的方法來解決這類問題。

回憶異或(XOR)運算的性質:

a XOR a = 0           a XOR 0 = a

我們從1異或到100,然后再和袋子里的數逐個異或,因為一個數與自身異或,結果是0,所以異或最后的結果就是丟失的數字。

Python 代碼:

def find_missing_1_number(sequence, n):
     """  returns the missing number of sequence, which is supposed to be
    a permutation of {1,..,n} with one number missing.
    
"""
    x = n
     for i  in xrange(1, n):
        x ^= i
     for e  in sequence:
        x ^= e
     return x

 

擴展問題一:如果其中兩個數字丟失了,怎么辦?

顯然,用上述方法不能同時求出兩個數。這是否意味着這種巧妙的方法不再適用了?讓我們先看一下,用上述方法求出的是什么。

設丟失的兩個數字為a和b,那么上述方法求出的結果就是 a XOR b。我們能否利用這個結果呢?答案是YES。因為a != b,那么

a 和 b 的二進制表示形式中一定至少有一位相異。我們可以根據該位把數字分成兩組,該位為0的一組和該位為1的一組。兩組分別

用上述方法異或,最后兩組異或的結果就是 a 和 b。

Python 代碼:

def find_missing_2_numbers(sequence, n):
     """  returns the missing two numbers of sequence, which is supposed
    to be a permutation of {1,..,n} with two numbers missing.
    
"""
    x = n
     for i  in xrange(1, n):
        x ^= i
     for e  in sequence:
        x ^= e
    diff = x & (-x)  #  isolates the rightmost 1-bit
    a, b = 0, 0
     for i  in xrange(1, n + 1):
         if i & diff:
            a ^= i
         else:
            b ^= i
     for e  in sequence:
         if e & diff:
            a ^= e
         else:
            b ^= e
     return a, b

注意在上面的方法中,我們要掃描兩遍這個序列。雖然復雜度仍是O(n),但是在某些特殊情況下,我們可能沒有第二次掃描的機會。

那么,能否只掃描一遍就算出結果呢?請看尋找丟失的數字(二)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM