涉及位運算子的操作的演算法

2021-10-11 00:24:39 字數 3510 閱讀 6204

異或運算 : 相同為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 按位異或運算子 當兩對應的二進位相異時,...