上一章咱們認識了按位操做符, 這一章咱們整理一下按位運算的經典案例html
使用按位操做符的數,會先轉成 32 位比特序列,也就是32 位的有符號的整數markdown
若是這個數是正數,若是大於 ,只會保留低 32 位, 高於 32 位的數不存儲;app
若是這個數是負數,若是小於 ,只會保留低 32 位, 高於 32 位的數不存儲;post
兩個二進制數, 它們對應位的數只有 1 個 1, 結果爲 1, 不然, 結果爲 0。spa
a ^ b ^ b = a
a ^ b = b ^ a
a ^ (b ^ c) = (a ^ b) ^ c
a ^ 0 = a
a ^ a = 0
12.12 ^ 0 //12
Math.PI ^ 0 //3
複製代碼
JavaScript 默認將數字存儲爲 64 位浮點數,但按位運算都是以 32位的二進制整數執行。code
兩個相同的數按位運算後, 結果只會保留整數部分,小數部分不存儲。orm
Infinity ^ 0 //0
Number.MAX_VALUE ^ 0 //0
複製代碼
若是一個數大於 , 按位運算時只會保留低 32 位運算, 高於 32位的數丟棄, 結果就不許確了。xml
3 ^ 3 //0
12.12 ^ 12.12 //0
複製代碼
let a = 3, b =5;
a = a ^ b;
b = a ^ b; // 分解開就是 (a ^ b) ^ b, 根據自反性得知,結果爲 a,a 賦值給 b
a = a ^ b; // 分解開就是 a ^ (a ^ b), 根據自反性得知,結果爲 b,b 賦值給 a
console.log(a, b) // 5, 3
複製代碼
咱們畫圖看一下:htm
a = 3 (base 10) = 00000000000000000000000000000011 (base 2)
b = 5 (base 10) = 00000000000000000000000000000101 (base 2)
--------------------------------
3 ^ 5 (base 10) = 00000000000000000000000000000110 (base 2) = 6 (base 10) = a
//如今 a = 6了
a = 6 (base 10) = 00000000000000000000000000000110 (base 2)
b = 5 (base 10) = 00000000000000000000000000000101 (base 2)
--------------------------------
6 ^ 5 (base 10) = 00000000000000000000000000000011 (base 2) = 3 (base 10) = b
//如今 b = 3 了, 已經把 a 的值交換給 b 了
a = 6 (base 10) = 00000000000000000000000000000110 (base 2)
b = 3 (base 10) = 00000000000000000000000000000011 (base 2)
--------------------------------
6 ^ 3 (base 10) = 00000000000000000000000000000101 (base 2) = 5 (base 10) = a
複製代碼
通過三次 ^
操做後, 咱們把 a 和 b的值交換成功了。
1-1000放在含有1001個元素的數組中,只有惟一的一個元素重複,找出這個重複的數字。
設重複的數爲 x, 根據自反性能夠獲得:
(1 ^ 2 ...... 999 ^ 1000)^ (1 ^ 2 ...... 999 ^ 1000 ^ x) = x
複製代碼
找出惟一一個在數組中出現一次的整數,而其餘都會出現兩次。
咱們知道兩個相同的數異或爲 0
, 那麼把數組中的全部整數異或運算, 剩下的就是惟一出現一次的數。
let arr = [1,2,1,2,3]
let value = arr.reduce((p, c) => p ^ c)
console.log(value) //3
複製代碼
一個整型數組
nums
裏除兩個數字以外,其餘數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。要求時間複雜度是O(n),空間複雜度是O(1)。
咱們把這一題拆分紅上面的那道題就好作了,拆分紅兩個數組分別異或。
const nums = [1, 4, 3, 4]
const x = nums.reduce((p, c) => p ^ c) //x = a ^ b
let mark = 1;
//兩個不相同的數, 異或對應位的數字至少有 1 位不相同, 咱們找出這個數.
while((x & mark) === 0) mark <<= 1;
let xor1 = 0;
let xor2 = 0;
for (let n of nums) {
if(n & mark){
xor1 ^= n;
}else{
xor2 ^= n;
}
}
console.log(xor1, xor2) //3,1
複製代碼
設 兩個不一樣的數是 a 和 b
x = a ^ b
a ^ b
的結果x
確定不爲 0,那麼至少有 1 位是 1, 咱們找出是哪一位?就能夠分組了。mark=1
,mark 會左移, 根據 x & mark
去找最近一位的 1,若是 x & mark
等於 1, 找到位置,不然, mark 繼續左移。mark
,咱們得知mark
中只有 1 位是 1, 其餘位都是 0, 因此遍歷nums
判斷n & mark
可得出:xor1
組,不然,放到xor1
組。n & mark
的值是同樣的, 確定會放在同一個 xor
中。