基本概念
異或運(yùn)算,符號(hào)為XOR或者^(guò),是二進(jìn)制的運(yùn)算,運(yùn)算法則為相同為0,不同為1,我記得時(shí)候反正總會(huì)忘(和同或記反),所以這里直接把異或理解為"不進(jìn)位的二進(jìn)制相加".舉個(gè)栗子:
1000111 和 1110001 異或
按照不進(jìn)位相加的運(yùn)算方法:最小位都是1 相加為2也就是10(二進(jìn)制運(yùn)算), 因?yàn)槭遣贿M(jìn)位的運(yùn)算 所以直接本位為0 就可以了,其他位如法炮制:0110110.
重要性質(zhì)
異或運(yùn)算符合交換律和結(jié)合律
交換律:a^b^c^d 和 a^d^c^b是一樣的
結(jié)合律:a^b^c^d和a^(b^c)^d是一樣的
0^N==N
N^N==0
應(yīng)用場(chǎng)景
1.利用異或交換兩個(gè)數(shù)
絕大多數(shù)這個(gè)操作都是沒(méi)屁硌楞嗓子的無(wú)意義操作....它的好處就是不用申請(qǐng)額外空間完成操作,但是不用異或操作也可以實(shí)現(xiàn)不申請(qǐng)額外空間的交換(異或操作還有可能出錯(cuò))---不創(chuàng)建臨時(shí)變量交換兩個(gè)變量傳送門(mén)(可以看下這篇博客)
int a = 10;
int b = 11;
a = a^b;
b = a^b;
a = a^b;
System.out.println(a);
System.out.println(b);
這三個(gè)a^b你懵不懵?反正我第一次看見(jiàn)是挺懵的
設(shè) a的初始值為x b的初始值為y
a = x^y
b = (x^y)^y 因?yàn)閥^y為0 x^0為x 所以b中現(xiàn)在存儲(chǔ)的數(shù)據(jù)為 x(交換完成)
a = x^y^x 同理 ==x
(寄!寫(xiě)著寫(xiě)著發(fā)現(xiàn)按值傳遞按址傳遞好不懸給忘了)
值得一提的是因?yàn)楫惢虿僮鞯男再|(zhì),如果a和b是同一塊內(nèi)存的話 會(huì)導(dǎo)致最后交換結(jié)果為0
2.一個(gè)數(shù)組中有一個(gè)數(shù)出現(xiàn)了奇數(shù)次,其他數(shù)都出現(xiàn)了偶數(shù)次,找到并打印這個(gè)數(shù)
這題用性質(zhì)做爽的一匹,直接把他們?nèi)籍惢蛟谝黄鹁托辛?根據(jù)結(jié)合律,出現(xiàn)偶數(shù)個(gè)的數(shù)全都異或在一起變成零,而奇數(shù)個(gè)數(shù)的數(shù)異或在一起會(huì)剩下一個(gè),然后本身和0異或還是本身;
public static int select(int arr[]) {
int sum = 0;
for(int i = 0;i<arr.length;i++) {
sum^=arr[i];
}
return sum;
}
public static void main(String[] args) {
int [] arr = {1,1,1,1,3,3,3,3,3,5,5,5,5};
int a = select(arr);
System.out.println(a);
}
3.取一個(gè)二進(jìn)制數(shù)中的最后一個(gè)1
如1001110 取得就是倒數(shù)第二個(gè)
我們先設(shè)N是一個(gè)二進(jìn)制數(shù)
N: 1 0 0 0 1 1 1 1 1 1 1
~N: 0 1 1 1 0 0 0 0 0 0 0(取反)
~N+1:0 1 1 1 0 0 0 0 0 0 1
然后把N和~N+1進(jìn)行按位與(&)操作
得到 0 0 0 0 0 0 0 0 0 0 1
public static int selectlastone(int n) {
int n1 = ~n+1;
int s = n&n1;
return s;
}
public static void main(String[] args) {
int n = 10;
System.out.println(Integer.toBinaryString(n));//按二進(jìn)制打印n
int a = selectlastone(n);
System.out.println(Integer.toBinaryString(a));//按二進(jìn)制打印a
}
4.一個(gè)數(shù)組中有兩個(gè)數(shù)出現(xiàn)了奇數(shù)次,其他數(shù)都出現(xiàn)了偶數(shù)次,找到并打印這個(gè)數(shù)
public static int select(int[] arr) {
int eor = 0;
for (int i = 0; i < arr.length; i++) {
eor ^= arr[i];
}
int rightOne = (~eor+1)&eor; // 提取出最右的1
int onlyOne = 0;
for (int i = 0 ; i < arr.length;i++) {
if ((arr[i] & rightOne) != 0) {
onlyOne ^= arr[i];
}
}
System.out.println(onlyOne);//onlyOne是其中一個(gè)
return eor ^ onlyOne;//返回的是另一個(gè)
}
public static void main(String[] args) {
int [] arr= {1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,4};
int a = select(arr);
System.out.println(a);
}
設(shè)這兩個(gè)單獨(dú)的數(shù)分別為a b
先把所有數(shù)字都異或在一起 偶數(shù)消除掉 留下的是 a^b
a和b至少有一位是不同的 所以a^b里面至少有一個(gè)1 我們?nèi)〕鲎笥疫叺? 得到rightone
a或者b不同的話 這個(gè)位置上肯定其中一個(gè)是 1 一個(gè)是 0;
我們假設(shè)a這個(gè)位置上是1 b這個(gè)位置上是0
(反正除了我們要找的數(shù)以外都是偶數(shù)個(gè),剩下的那些本位置為1的數(shù)是0個(gè)還是6個(gè)8個(gè)都不重要)
可以把這個(gè)數(shù)組分為兩組 A組 這個(gè)位上為1的元素 B組 這個(gè)位上為0的元素
而在A組中 包含偶數(shù)個(gè)其他元素和奇數(shù)個(gè)a 所以再次轉(zhuǎn)變成問(wèn)題2求出onlyone
然后再有a^b = eor a^eor = b 求出另一個(gè)元素文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-467084.html
5.求二進(jìn)制數(shù)中有多少個(gè)1
public static int onecount(int a) {
int count = 0;
while(a!=0) {
int rightone = ((~a)+1)&a;
count++;
a ^= rightone;
}
return count;
}
public static void main(String[] args) {
int a = 55;
int count = onecount(a);
System.out.println(count);
}
用應(yīng)用3輕松解決文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-467084.html
到了這里,關(guān)于Java-異或運(yùn)算詳解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!