異或運算 : 相同為0,不同為1 –記成無進製相加同或運算 : 相同為1,不同為0
6^7
=1110^
111(二進位制)
----
----
--001
(無進製相加)
異或預算的性質
1)0
^ n ==n n ^ n ==02
) 異或運算滿**換律和結合律 : 只要同一批數異或起來的結果都是一樣的(不用管順序)
這兩個性質用無進製相加來理解就非常容易了
題目一:如何不用額外變數就交換兩個數的值int a = 甲;
int b = 乙;
----
----
-a = a ^ b;
----
-> a = 甲 ^ 乙, b = 乙
b = a ^ b;
----
-> a = 甲 ^ 乙, b = 甲 ^ 乙 ^ 乙 = 甲 ^
0= 甲
a = a ^ b;
----
-> a = 甲 ^ 乙 ^ 甲 = 甲 ^ 甲 ^ 乙 =
0^ 乙 = 乙, b = 甲
正好調換位置 -- 因為有兩個空間,這兩個空間能夠相互倒換過來
----
但是這種做法需要注意的一點是:如果交換位置,兩個變數指向的記憶體位址一樣,那麼沒有多餘的記憶體位址用來交換,那麼異或出來就是0
顯然會出現問題.
這種交換可以不用這樣寫,沒必要題目二: 乙個陣列中只有一種數出現了奇數次,其他數都出現了偶數次,怎麼找到並列印這種樹
準備乙個變數 eor = 0, 陣列 [a,b,c…]eor = eor ^ a = a;
eor = eor ^ b = a ^ b
…最終eor是啥,就是這個出現了奇數次的數
[2,
1,3,
2,2,
4,1,
3,1,
2,4,
1,4]
===1出現4次,
2出現4次,
3出現2次,
4出現3次
異或運算跟順序無關
所以異或可以看成:[1
,1,1
,1,2
,2,3
,3,4
,4,4
]------
----
----
----
----
----00
004=
4(不用先排序)
實現**
public
static
void
printoddtimesnum1
(int
arr)
system.out.
println
(eor)
;}
題目三:怎麼把乙個int型別的數,提取出最右側的1來n = 0......000011010000變成:
n = 000...0000000010000 (只把他最右側的1取出來,其他的都變成0)
這個技巧是刷題過程中經常遇到的,這種技巧是種常規操作
n &((
~n)+1)
n =0..
....000011010000
~n =1..
....111100101111
~n +1=
1....
..111100110000
n &(
(~n)+1
)=0..
....000000010000
題目四:乙個陣列中有兩種數出現了奇數次,其他數都出現了偶數次,怎麼找到並列印這兩種數假設陣列 arr中,a跟b出現了奇數次,其他的都出現了偶數次
前提是 a 和 b 一定是不等的
用eor去挨個異或陣列中每個數,那麼得到的結果是 a ^ b
那意味著 eor = a ^ b 不等於 0
,這一點說明 eor = a ^ b 一定在某個位上有 1
假設在第八位上是1
-- 這也說明 a 的第八位 跟 b 的第八位 一定是不一樣的**
***我們現在得到的結論有 :
1) a 不等於 b,
2) eor = a ^ b 的值,
3) a ^ b 在某一位上一定是1**
***所以整個陣列(包含出現奇數次和偶數次的數)就可以分成兩大類:
1.第8位上是1的數
2.第8位上是0的數
但是 a 跟 b 肯定不是同一類的(異或得出來的結果)
----
----
----
-然後再準備乙個 eor`,用eor`只異或第八位上是1的數,而第八位上是1的數出現偶數次的數依然不會干擾,仍然是0
,所以最後
要麼a要麼是b被抓住,乙個出現了,另乙個異或也會出現
實現**
public
static
void
printoddtimesnum2
(int
arr)
// 此時 eor = a ^ b
// eor != 0
// eor 必然有乙個位置上是1
/* * 如果 a ^b = 0110010000
* 那麼 rightone = 000010000
* */
int rightone = eor &
(~eor +1)
;// 提取出最右的 1
int onlyone =0;
// eor`
for(
int i =
0; i < arr.length; i++)}
system.out.
println
(onlyone +
" "+
(eor ^ onlyone));
}
技巧:怎麼把乙個int型別的數,提取出最右側的1來,這個技巧的應用還是挺多的,再看乙個例子
題目五:如何把乙個數的二進位制1的個數獲取出來
暴力法的話,
int型別32位,遍歷32次.
實現**
public
static
intbit_1_counts
(int num)
return count;
}
根據左程雲老師授課整理而成 位操作運算子
1.按位與運算子 按位與運算子 是雙目運算子。其功能是參與運算的兩個數字對應的二進位制位相與。只有對應的兩個二進位均為1時,結果位才為1,否則為0。參與運算的數以補碼方式出現。例如,9 5可寫算式如下 00001001 9的二進位制補碼 00000101 5的二進位制補碼 00000001 1的二進...
位運算子 操作符
按位與 按位或 取反 按位異或 按位異或可以實現兩個變數值的交換,但是並不推薦。a b b a a b 都是雙目運算子,將二進位制向左移動指定位,高位丟棄,低位補0.當為負數時,根據編譯系統的規定補0,或者1.例 0x01 2 3 這裡要考慮運算子的優先順序。的優先順序大於 的優先順序,所以0x01...
Python 位操作運算子
按位與運算子 參與運算的兩個值,如果兩個相應位都為1,則該位的結果為1,否則為0 a b 輸出結果 12 二進位制解釋 0000 1100 按位或運算子 只要對應的二個二進位有乙個為1時,結果位就為1。a b 輸出結果 61 二進位制解釋 0011 1101 按位異或運算子 當兩對應的二進位相異時,...