一. 異或運算 ^
december 13, 2012 | 3 minute read
不介紹什麼是異或了,有人叫半加、數學系的叫按位模2加
下文用得到的一些簡單的性質
下面是幾個小題目,可以用異或解決,挺有技巧性
a = a^b
b = a^b
a = a^b
update_2013-05-06: 這個,看到雲風寫了乙個利用這個特性做的雙向鍊錶,挺好玩,忍不住寫過來。
令xor(x)
表示將x集合內所有的數做異或
xor(b)^xor(a) = xor(b)^xor(b)^x = 0^x = x
a = (1..10000).to_a
b = a - [1234]
x = (a + b).reduce(&:^)
puts x #1234
via:
首先按上乙個的辦法可以推導出xor(a)^xor(b) = xor(b)^xor(b)^x^y = 0^x^y = x^y
x^y
的二進位制結果,第n位為1,說明x和y的第n位不相同
根據第n位是否為0把a裡所有的數分成a1和a0兩個陣列(a1裡的數的二進位制第n位都是1,a0都是0)
a1和a0應該各包含了a或者b(這樣第n位才能異或出1)
同理可以把b分成b1和b0兩個陣列
可以得到第乙個數x = a1^b1
第二個數可以y = a0^b0
,當然也可以用x^y^x
求得
另外如果x^y
為0,即x == y
,令sum(x)
為x集合內所有數求和
(sum(a) - sum(b)) / 2 = x
via:
xor(a) = x^y^y^…^z^z = x^(y^y^…^z^z) = x^0 = x
x = a.reduce(&:^)
xor的本質相當於「按位模2加」(adding modulo 2),令p1,p2…pn為布林值,true為1、false為0,(+)表示異或操作。
p1 (+) p2 (+) ... (+) pn == ( p1 + p2 + ... + pn ) % 2
所以只需要實現按位模3加
( p1 + p2 + ... + pn ) % 3
將集合中所有數二進位制表示的同一位的0或1相加,最終的和對3去摸,得到的數即是x
如a =
,二進位制表示兩個數
101
111111
+ 111
------
434% 3
------
101
但願這坨東西能讓人看懂
via:
這裡的轉換有很多,比如下面這個
x ^ y == (~x & y) | (x & ~y)
具體檢視維基百科 《equivalencies, elimination, and introduction》部分,各種公式
實際運用如下:
最近上leetcoude刷題,題目如下
這個題目要求找出陣列中唯一一次只出現一次的數字(其他數字出現2次),題目本身很簡單,但是想要寫出o(n)的演算法還是需要點技巧的。
這個題目如果是求陣列的和,大家都能寫出o(n)的實現,只用單純的遍歷相加即可。但若要求出其中唯一單次出現的數字時,便沒有這麼直觀了。不過可以基於相加做一些聯想,是否有另外一種運算法則,使得相同的值運算結果為零,不同的值運算結果體現為加?這個聯想可能有點莫名其妙,不過熟悉異或運算的基本性質(結合律),將運算看成二進位制的運算就能夠理解了。異或運算的「半加」特性可以理解為基於二進位制的加法,但是不進製,也就是說加法溢位時丟棄進製。聯想到題目上就是,相同的兩個數異或得0,剩下唯一的乙個單個數字與所有成對的結果0異或,得到唯一得數字。
拓展思維,基於不同的場景,如果能夠對於場景構思出一種滿足結合律得運算方式,那麼這個問題就可以使用乙個o(n)的演算法來解決!
位運算總結與應用
一 求下面函式的返回值 int func x return count 功能 將x轉化為2進製,看含有的1的個數。每執行一次x x x 1 會將x用二進位制表示時最右邊的乙個1變為0,因為x 1將會將該位 x用二進位制表示時最右邊的乙個1 變為0。二 下面函式的作用 bool func int x ...
位運算的應用
1.對特定位清0 mask中的特定位為0,其餘位為1。s s mask 2.取某數中的指定位 mask特定位置1,其餘位0。常用來將源運算元某些位置1,其餘位不變 mask特定位置為1,其餘位為0。1.使特定位取反 mask特定位置1,其餘位為0 2.不引用第三方變數,交換值 a a b b a b...
位運算的應用
使用pascal的oiers簡要介紹一下c c 樣式的位運算 bitwise operation 其優先順序 not and xor or 名稱 c c 樣式 pascal樣式 簡記法則 按位與 and 全一則一,否則為零 按位或 or 有一則一,否則為零 按位取反 not 是零則一,是一則零 按位...