前言
很久没有写博客了,在2021年的最后时间里,来更新一下2021最后一篇博客,希望看客们万事如意,新的一年快乐顺心。
位运算
众所周知,程序中的所有数在计算机内存中都是以二进制的形式储存的。然后我们的位运算就是直接对整数在内存中的二进制位进行操作。位运算功能强大,是很多题目的不二之选。
(图片来源网络,侵删)
位运算基本运算符如图所示,下面来依次实现:
左移
位运算的左移就是把一个数的往左边移动,原来的位置上补零:
a=5
print(a<<1)
输出:
可以看出,位运算左移一位相当于乘以二。
右移
位运算右移和位运算左移恰好相反,把二进制位往右边移动,原来的位置补零,相应的,右移一位相当于除以二。
a=6
print(a>>1)
输出:
那么位运算右移相当于除以二,我们常用的二分法中的代码就可以做出改变:
二分法:
class Solution:
def searchInsert(self, nums, target) :
a=sorted(nums)
left ,right = 0, len(a)-1
while right >= left:
mid=(left+right)//2
if a[mid]==target:
return mid
if target>a[mid]:
left=mid+1
else:
right=mid-1
return False
把除号改变成右移的二分法:
class Solution:
def searchInsert(self, nums, target) :
a=sorted(nums)
left ,right = 0, len(a)-1
while right >= left:
mid=(left+right)>>1
if a[mid]==target:
return mid
if target>a[mid]:
left=mid+1
else:
right=mid-1
return False
按位或
按位或操作就是用二进制位每一位对比,当都是零是才为零,其余为一。
print(1|2)
输出:
按位与
按位与和按位或也是恰恰相反,按位与是只有两个同时为一时才为一,其余为零。
print(1&2)
输出:
异或
异或操作是对每一位二进制进行,相同为零,不同为一。所以每一个数与零异或都是它本身,每一个数与它本身异或都等于零。有一个通俗的理解方式,位运算的异或操作相当于不进位(不进位是指二进制不进位)的加法。
print(1^6)
输出:
取反
取反,顾名思义就是把数字按位取得相反的,零变成一,一变成零。
print(~(-2))
输出:
位运算应用
说了位运算的基本操作,现在来实际操作一下。以力扣题(简单难度)为例。
位1的个数
力扣连接.
我们想要统计1的个数,根据上面说的两数相与,不难想到,我们把每一位与1进行按位与运算,如果这个位是0,那么就不会累加,如果是1,那么就会把这个数加一,也就相当于统计了一个1。
class Solution:
def hammingWeight(self, n: int) -> int:
count=0
while n:
count+=n&1
n=n>>1
return count
汉明距离
力扣连接.
汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字对应位不同的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。
上面解释来自于百度百科,我觉得题解百度百科已经说的很好了,只是力扣的翻译有点拗口,可能会导致我们理解错误。
class Solution:
def hammingDistance(self, x: int, y: int) -> int:
n=x^y
count=0
while n:
count=count+(n&1)
n=n>>1
return count
交替位二进制数
力扣连接.
这道题其实很简单,我们想要知道它是不是交替进行的,只需要将它错位异或,所谓错位异或,就是将这个数左移或者右移一位再与原来的数异或。如果是交替出现的,此时的数异或值一定全是一,然后我们知道它全是一,只需要把它加一再与异或后的相与,如果结果等于零就是交替出现的。
class Solution:
def hasAlternatingBits(self, n: int) -> bool:
x=(n>>1)^n
return x&x+1==0
找不同
力扣连接.
我们想要知道哪一个数是添加进去的,只需要把了两个字符串拼接起来,然后原本有的字母就出现了两次或者偶数次,就只有添加进去的字母只出现了一次或者奇数次,所以我们采用位运算异或,因为两个数相与会得到零,所以定义一个初始数字为0,然后与每一位异或,最后的数字对应的字母就是被添加的字母。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
ans=0
for i in s+t:
ans^=ord(i)
return chr(ans)
二进制求和
上面说过,异或相当于不进位的加法,所以遇到加法的题且不让使用四则运算符号的时候就可以使用位运算来进行解答,加上进位运算就可以解答题目。
class Solution:
def addBinary(self, a: str, b: str) -> str:
x = int(a,2)
y = int(b,2)
while y:
sum=x^y
ans=(x&y)<<1
x,y=sum,ans
return bin(x)[2:]
2的幂
一个数如果是二的幂,那么它就只包含一个1(二进制)。有了这个思路,我们的解题变得很简单。统计1的个数即可。
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
if n<0:
return False
count=0
while n:
count+=n&1
n>>=1
return count==1
附:位运算与其他方法对比
上文中找不同和位一的个数均可使用python字典求解,此处提供找不同题目的解答。
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
dic={}
for wors in s+t:
dic[wors]=dic.get(wors,0)+1
return "".join([key for key in dic if dic[key]%2!=0])
用时:
内存:
位运算所用时和内存;
本人python初学者,如有错误,还请帮忙斧正,感激不尽。