方法一:逐位判断
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += n & 1
n >>= 1
# n //= 2 # 计算时间长
return res
方法二:巧用 n & (n - 1)
class Solution:
def hammingWeight(self, n: int) -> int:
res = 0
while n:
res += 1
n &= n - 1
return res
剑指 Offer 65. 不用加减乘除做加法
直接看题解了。。。
提示:
a, b 均可能是负数或 0
结果不会溢出 32 位整数
不太懂的看下面解释
一句话来说就是:python在进行运算时会用负数的补码形式去运算,然后输出结果的时候会将补码转换成原码输出(正数的补码就是他本身)
这个“补码转换成原码输出”的过程是python内部自己完成的,python在输出时会以十进制形式(自己实现可以将补码取反+1)
我们现在要做的事情是:将以补码形式表示的负数转换成十进制输出,我们要做的就是如下两个步骤:
1.将负数的补码高位还原(前面我们把负数的高位全都置为了0)
2.将正确的补码(高位全为1)送入python中让他输出一个十进制数
首先思考:怎么将补码高位还原呢?我们可以将高于32的数位取反(0到1),但是直接取反会将低于32的数位也取反,所以我们先对低于32的数位做一次取反,再整体取反,就可以实现只对高于32的数位取反啦。
对低于32的数位取反可以通过和0xffffffff异或来实现,这个异或操作也不会改变高于32的数位(0与0异或还是0)
还有一个小小的疑惑点就是,为啥~操作之后就会输出正确的值呢?
因为~操作之后我们会得到高位全为1的负数的补码,python会将这个补码转换成十进制输出。
总的来说,这些操作做的事情就是:
1.手动取出负数位数为32的补码(a&0xffffffff)
2.将补码还原成原码(先将补码高位置1还原成python中真正的补码,python会自动将补码转换为十进制输出)
作者:grace-27
链接:https://leetcode-cn.com/problems/bu-yong-jia-jian-cheng-chu-zuo-jia-fa-lcof/solution/pythonjie-fa-xiang-xi-jie-du-wei-yun-sua-jrk8/
来源:力扣(LeetCode)
理解了这个,才到正文,如何用位运算。
class Solution:
def add(self, a: int, b: int) -> int:
x = 0xffffffff # 4*8=32位
a, b = a & x, b & x
while b != 0:
# a, b = (a ^ b), (a & b) << 1 & x
# 因为补码运算,第32位在进1,不一定代表溢出,可能有负数转为正数
c = (a & b) << 1 & x # 进位 这里还是只保留32位
a ^= b # 非进位和
b = c # 进位
return a if a <= 0x7fffffff else ~(a ^ x)



