位運算就是直接對整數(shù)在內存中的二進制位進行操作,位運算的性能較高,常用的位運算包含按位與&,按位或|,按位非~,按位異或 ^,有符號左移<<,有符號右移 >>。
如下是一些妙用的示例:
判斷奇偶
常用思路通過除以2,判斷余數(shù)是否為0:
def isodd(x):
return True if (x % 2 <> 0) else False
如何使用位運算,我們只需要使用&運算,與1進行&,如果為1,那么該數(shù)為奇數(shù);如果為0,那么該數(shù)是偶數(shù),Python代碼如下:
def isodd(x):
return True if (x & 1) else False
左移和右移
左移一次相當于乘以2,右移一次相當于除以2
a = 10
b = 20
a << =1
b >> =1
# a = 20
# b = 5
交換數(shù)值
常用思路如下:
tmp = b
b = a
a = tmp
異或運算的特性:任意數(shù)和自身異或結果為0;0和任意數(shù)異或結果還是其本身。 使用位運算則如下:
a ^= b
b ^= a
a ^= b
第一行,a = a ^ b,很容易理解;
第二行, b = b ^ a = b ^ a ^ b,由于 b ^ b = 0,所以 b = a ^ 0,即 b = a;
第三行, a = a ^ b ,由于a在第一步重新賦值,所以,a = a ^ b ^ a = b,完成了數(shù)值交換。
尋找數(shù)據(jù)列表中的獨一無二
有一個數(shù)據(jù)列表(2N+1個整數(shù)),只有一個數(shù)出現(xiàn)了1次,其余N個數(shù)都出現(xiàn)了2次。如何找到這個獨一無二的數(shù)據(jù)?
看到這個題目,相信大家第一次想到的算法肯定是計數(shù),建立列表,循環(huán)整個數(shù)據(jù)并計數(shù),然后遍歷這個列表找到出現(xiàn)次數(shù)為1的數(shù)據(jù)。
這樣,空間復雜度為O(N)。
如何降低空間復雜度呢?
注意看一下剛剛講過的異或的特性:任意數(shù)和自身異或結果為0;0和任意數(shù)異或結果還是其本身。
那么,出現(xiàn)了2次的N個數(shù)異或的結果是0,再與出現(xiàn)次數(shù)為1次的數(shù)異或的結果即為該數(shù)。即:找到這個獨一無二數(shù)據(jù)的辦法是通過對全部的數(shù)據(jù)進行異或操作,空間復雜度降低為O(1)。
計算一個數(shù)值的二進制數(shù)中有多少個1
相信有了之前的基礎,大家很容易實現(xiàn)這個算法。單純的通過位運算,與1進行與運算,看是否結果為1,然后右移1位,繼續(xù)判斷。Python代碼實現(xiàn)如下:
def number1Bit(x):
count = 0
while x:
count = count + (x&1)
x = x >> 1
return count
這樣存在一個問題,就是如果有連續(xù)多個0,那么需要做多次移位操作。有沒有簡單的方式跳過連續(xù)多個0的情況?
那就是通過與(x-1)進行&運算。這里可能不太好理解,舉例說明一下
x 1110 0000
x - 1 1101 1111
x&(x-1) 1100 0000
通過這種方式,會把最后的那個1檢測出來。
Python代碼實現(xiàn)如下:
def number1Bit(x):
count = 0
while x:
count = count + 1
x = x & (x-1)
return count