題目1
一個無序的數組裏面有若干個正整數,範圍是1-100,其中的99個整數都出現了偶數次,只有1個整數出現了奇數次,如何找到這個出現奇數次的整數?
思路
遍歷整個數組,依次做異或運算。由於異或運算在進行運算時,相同爲0,不同爲1,因此所有出現偶次的整數都會相互抵消成爲0,只有唯一出現奇數的整數會被留下。
如:
無序數組 | 3 | 1 | 3 | 2 | 4 | 1 | 4 | |
---|---|---|---|---|---|---|---|---|
異或運算 | 3 xor | 1 xor | 3 xor | 2 xor | 4xor | 1 xor | 4 xor | =2 |
假設數組長度爲n,那麼該解法的時間複雜度是O(n),空間複雜度爲O(1)。
題目2
假設一個無序數組裏有若干個正整數,範圍是1-100,其中有98個整數出現了奇數次,其他的整數出現偶數次。如何找出這個2個出現奇次整數?
思路
把2個出現奇數次的整數命名爲A和B,遍歷整個數組,然後依次做異或運算,進行異或運算的最終結果,等於A和B進行異或運算的結果。在這個結果中,至少有一個二進制單位是1(如果是0,說明A和B相等。和題目不符)
如:無序數組{4,1,2,2,5,1,4,3},所有元素進行異或運算的結果是00000110B
無序數組 | 4 | 1 | 2 | 2 | 5 | 1 | 4 | 3 | |
---|---|---|---|---|---|---|---|---|---|
異或運算 | 1 xor | 1 xor | 2 xor | 2 xor | 5xor | 1 xor | 4 xor | 3 xor | 00000110B |
選定該結果中的值爲1的某一位數字,如00000110B的倒數第2位是1,這說明對應的A和B的二進制的倒數第2位是不同的。其中必定有一個是0,有一個是1
根據這個結論可以把原來的數字按照二進制的倒數第2位的不同,分爲兩個部分,一部分的倒數第2位是0,另外一部分的倒數第2位是1。如:
5—>>二進制—>>101
3—>>二進制—>>011
倒數第2位,一個是0,一個是1
所以按照以上方法可將數組分爲:
4,1,5,1,4和2,2,3兩個部分。
接下來按照原來的異或運算,從每一部分找出唯一的奇數次即可。
假設數組長度爲n,那麼該解法的時間複雜度是O(n)。把數組分成兩個部分,並不需要額外的存儲空間,完全可以按照二進制位分組的同時來做異或運算,所以空間複雜度仍然是O(1)。
代碼
def findLostNumber(array):
# 用於存儲出現奇次的整數
resultList = [0 for i in range(2)]
# 第一次做整體異或運算
xorResult = 0;
for i in array:
xorResult^=i
if xorResult==0:
return None
# 確定2個整數的不同位,以此來做分組
separator = 1
while 0==(xorResult&separator):
separator<<=1;
# 第二次分組進行異或運算
for j in array:
if 0==(separator&j):
resultList[0]^=j
else:
resultList[1]^=j
return resultList
if __name__ == '__main__':
array = [4,1,2,2,5,1,4,3]
res = findLostNumber(array)
print(res)