異或運算及其應用


異或是一種基於二進制的位運算,用符號XOR或者 ^ 表示,

其運算法則是對運算符兩側數的每一個二進制位,同值取0,異值取1。

它與布爾運算的區別在於,當運算符兩側均為1時,布爾運算的結果為1,異或運算的結果為0。

一、異或的性質

  1. 交換律:a ^ b = b ^ a
  2. 結合律:a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c
  3. d = a ^ b ^ c 可以推出 a = d ^ b ^ c
  4. 自反性:a ^ b ^ a = b

 

二、異或的應用

交換兩個數

最常見的做法就是增加一個臨時變量,代碼如下:

 

    public void switchValue(int a, int b) {
        System.out.println("Before switch:    a:" + a + "\tb:" + b);
        int temp = b;
        b = a;
        a = temp;
        System.out.println("After switch:    a:" + a + "\tb:" + b);
    }

 

升級版,將兩個數加減來實現,代碼如下:

    public void switchValue(int a, int b) {
        System.out.println("Before switch:    a:" + a + "\tb:" + b);
        a = a + b;
        b = a - b;
        a = a - b;
        System.out.println("After switch:    a:" + a + "\tb:" + b);
    }

利用異或運算,也可以將兩個數交換,例如:

public void switchValue(int a, int b) {
        System.out.println("Before switch:    a:" + a + "\tb:" + b);
        a = a^b;
        b = a^b;
        a = a^b;
        System.out.println("After switch:    a:" + a + "\tb:" + b);
}

 

 算法題目

 ①1-1000放在含有1001個元素的數組中,只有唯一的一個元素值重復,其它均只出現一次。每個數組元素只能訪問一次,設計一個算法,將它找出來;不用輔助存儲空間,能否設計一個算法實現?

解法一:將所有數加起來,減去1+2+...+1000的和。

這個算法已經足夠完美了,相信出題者的標准答案也就是這個算法,唯一的問題是,如果數列過大,則可能會導致溢出。
解法二:異或就沒有這個問題,並且性能更好。將所有的數全部異或,得到的結果與1^2^3^...^1000的結果進行異或,得到的結果就是重復數。

解法一很顯然,解法二需要證明一下:

前面提到異或具有交換律和結合律,所以1^2^...^n^...^n^...^1000,無論這兩個n出現在什么位置,都可以轉換成為1^2^...^1000^(n^n)的形式。
其次,對於任何數x,都有x^x=0,x^0=x。
所以1^2^...^n^...^n^...^1000 = 1^2^...^1000^(n^n)= 1^2^...^1000^0 = 1^2^...^1000(即序列中除了n的所有數的異或)。

令,1^2^...^n^..^1000(序列中包含一個n)的結果為T 
則1
^2^..^n^..^n^..^1000(序列中包含2個n)的結果就是T^n。
T
^(T^n)=n。
所以,將所有的數全部異或,得到的結果與1
^2^3^...^1000的結果進行異或,得到的結果就是重復數。

 

②一個數組存放若干整數,一個數出現奇數次,其余數均出現偶數次,找出這個出現奇數次的數?

這個其實是①的一個變形題目,最直接的辦法還是和上面一樣,就是把所有數異或 (奇數個異或是本身,偶數個是0)

 

 

參考資料:http://www.cnblogs.com/kaituorensheng/archive/2013/04/04/3000033.html

 

 

 

 


免責聲明!

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



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