位运算就是直接对整数在内存中的二进制位进行操作,位运算的性能较高,常用的位运算包含按位与&
,按位或|
,按位非~
,按位异或 ^
,有符号左移<<
,有符号右移 >>
。
如下是一些妙用的示例:
判断奇偶
常用思路通过除以2,判断余数是否为0:
def isodd(x):
return True if (x % 2 <> 0) else False
如何使用位运算,我们只需要使用&运算,与1进行&,如果为1,那么该数为奇数;如果为0,那么该数是偶数,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
交换数值
常用思路如下:
tmp = b
b = a
a = tmp
异或运算的特性:任意数和自身异或结果为0;0和任意数异或结果还是其本身。 使用位运算则如下:
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,完成了数值交换。
寻找数据列表中的独一无二
有一个数据列表(2N+1个整数),只有一个数出现了1次,其余N个数都出现了2次。如何找到这个独一无二的数据?
看到这个题目,相信大家第一次想到的算法肯定是计数,建立列表,循环整个数据并计数,然后遍历这个列表找到出现次数为1的数据。
这样,空间复杂度为O(N)。
如何降低空间复杂度呢?
注意看一下刚刚讲过的异或的特性:任意数和自身异或结果为0;0和任意数异或结果还是其本身。
那么,出现了2次的N个数异或的结果是0,再与出现次数为1次的数异或的结果即为该数。即:找到这个独一无二数据的办法是通过对全部的数据进行异或操作,空间复杂度降低为O(1)。
计算一个数值的二进制数中有多少个1
相信有了之前的基础,大家很容易实现这个算法。单纯的通过位运算,与1进行与运算,看是否结果为1,然后右移1位,继续判断。Python代码实现如下:
def number1Bit(x):
count = 0
while x:
count = count + (x&1)
x = x >> 1
return count
这样存在一个问题,就是如果有连续多个0,那么需要做多次移位操作。有没有简单的方式跳过连续多个0的情况?
那就是通过与(x-1)进行&运算。这里可能不太好理解,举例说明一下
x 1110 0000
x - 1 1101 1111
x&(x-1) 1100 0000
通过这种方式,会把最后的那个1检测出来。
Python代码实现如下:
def number1Bit(x):
count = 0
while x:
count = count + 1
x = x & (x-1)
return count