異或運算實現數值交換
package dataStructuresAndAlgorithms;
public class BitOperation {
public static void main(String[] args){
int a = 2;
int b = 3;
a = a^b; // a = 2^3 b = 3;
b = a^b; // a = 2^3 b = 2^3^3 = 2
a = a^b; // a = 2^3^2 = 3 b = 2
System.out.println("a = "+a+ " b = "+b);
}
}
解析:
1、0 與任何數異或,得到數的本身,任何數和自身進行異或,得到0;
2、數學的交換律和結合律適用於異或運算,即:a^b = b^a; a ^ b ^ c = a ^ ( b ^ c);
3、這種交換方式的實現前提是,變量所指的地址必須不同,值可以相同;
注:異或運算可理解為不進為的二位運算,即:1+1 =0; 1+0 = 1;
異或面試題
1、數組中,有一種數出現的次數是奇數次,其余的都是偶數次,查找出這個數;
2、數組中,有倆種數出現的次數是奇數次,其余的都是偶數次,查找出這倆個數;
解:
1:
public static void getOddNumber(){
int[] arr = {2,3,2,2,3,3,2,6,6,7,6,7,6};
int eor = 0;
for(int number:arr){
eor = eor^number;
}
System.out.println(eor);
}
運行結果:3
分析:異或運算滿足交換律和結合律,與元素的異或順序無關,將數組種,相同的元素交換到一起,即可獲得:
{2,2,2,2,3,3,6,6,6,6,7,7}
出現次數為偶數的數字,經過異或運算,會成為0,剩余的元素即為出現次數為奇數的元素。
2:
//獲取出現次數為奇數的倆個元素 a,b
public static void getTwoOddNumber(){
int[] arr = {3,3,4,6,6,8,7,7,7,8,8,8};
int eor = 0;
/*
* 異或運算完,此時:eor = a^b = 4^7
* 即:eor != 0,
* 可得: eor的二進制上,必有一個位置不為0
* */
for(int number:arr){
eor = eor^number;
}
/*
* ~eor: 為取反操作,列:eor = 100000011 則~eor = 011111100
* ~eor+1: 例:~eor = 011111100 ,則: ~eor+1 = 01111101
* eor & (~eor+1):與運算 例: eor & (~eor+1) = 11111111(同為1則為1.否則為0)
* 此寫法能夠找出右邊第一出現1的數
* 現在已經找出 eor = a^b 上為1的位置
* */
int rightOne = eor & (~eor + 1);
/*
* 已經得出eor不為0的位置,進行與運算時,會自動將出現次數為偶數的元素消掉
* 當數組元素與rightOne進行與運算時,出現為0或者1的數,即為a或者b
* */
int onlyOne = 0;
for(int number : arr){
if((number & rightOne) == 0){
onlyOne ^= number;
}
}
/*
* 將已經得到的出現次數為奇數的一個數,與eor進行異或運算,即可得到另一個數
* */
int otherOnlyOne = eor^onlyOne;
System.out.println("一個數為:"+onlyOne+" 另一個是:"+otherOnlyOne);
}
運行結果:一個數為:4 另一個是:7