1,異或運算的規則:
a) 0 xor 0 = 0
b) 0 xor 1 = 1
c) 1 xor 0 = 1
d) 1 xor 1 = 0
2, 異或運算的性質:
a) a xor a = 0
b) (a xor b) xor c = a xor (b xor c)
c) IF a xor b = c THEN a xor c = a xor (a xor b) = (a xor a) xor b = b
3, 異或的應用
Q1: 一個數組,除其中一個元素(如下面的99),其它的都是成對出現的,如何能快速找出那99的位置
……102,102,2,2,44,44,99,23,23,11,11 ……
請參考:
參考貼子
Answer 1:
把所有數組元素全部異或一下則得到非成對出現的元素99,然後順序查找99的位置。時間複雜度爲O(n)。
此解法較通用,適合如下兩種特殊情況:
a),如……102,102,2,2,2, 2,44,44,99,23,23,11,11 ……(連續但存在相同元素)
b),如...... 102,2,44,23,11,99,11,23,44,2,102......(配對但不連續)
若數據無素不會出現3(a)和(b)中情況,那麼可以採用一種更高效的算法:
Answer 2:
折半查找。
若數組a的元素個數爲(n+1),則n+1必爲奇數。數組a的序號爲0到n。
left = 0; right = n; m = (left+right)/2;
int find99(left,right);
m = (n+0)/2,
IF: m爲偶數,也即m兩邊的數量都爲偶數,分別判斷a[m]與a[m-1]、a[m+1]的值,若與a[m-1]相等,則99必在左側,那麼接下來就find99(left,m-1)。若與a[m+1]相等,則99必在右側,那麼find99(m+1,right)。若都不相等,則a[m] == 99,return m。
ELSE: 若m爲奇數,也即m兩邊的數量都爲奇數,分別判斷a[m]與a[m-1]、a[m+1]的值,若與a[m-1]相等,則99必在右側,find99(m+1,right)。若與a[m+1]相等,則99必在左側,find99(left,m-1)。若都不相等,則a[m] == 99,return m。
Q2:一個很大的數組,裏面有兩個數只出現過一次,其他數都出現過兩次,把這兩個數找出來
ref :參考貼子
Answer 1:
在題目給出的很大的數組中,除要找的兩個不同的數字外,其它的數字都是成對出現的,根據上面說到的兩個相同的數字的異或其結果爲0。因此,如果將整個數組中的元素進行異或,所得到的結果應該是所求的那兩個不成對的數字的異或結果。
假定數組中兩個不同的數字是95 ^ 99,則其異或的結果是0111100b,其中有4位是1,這表明這兩個數字的二進制表示中有4位是不同的。(從右往左數) 它們分別是第3、4、5、6這4位,於是我們只需要
將數組中所有元素中第6位爲1的元素和0111100b異或,
or,將數組中所有元素中第5位爲1的元素和0111100b異或,
or,將數組中所有元素中第4位爲1的元素和0111100b異或,
or,將數組中所有元素中第3位爲1的元素和0111100b異或。
就可以得到所求之兩個數字中的一個數字。
不妨以上面最後一條規則爲例來進行說明:數組元素中第3位爲1的數字,除所求的兩個數字之外,都是成對出現的,它們所產生異或的結果肯定是0。而所求的那兩個數字當中只有一個數字的第3位1。不妨假定這個數字是a(此時未知),另外一個要求的數字是b(此時未知)。很明顯,將a (此時未知)和0111100b異或就可以得到b (此時已知),再用0111100b和已經求出來的b (此時已知) 進行異或就可以得到a (此時已知)。比如上面的95的第3位爲1,所以用95 ^ 0111100b = 1011111b ^ 0111100b = 1100011b = 99,再用99 ^ 0111100b = 1100011b ^ 0111100b = 1011111b = 95。