1 问题
输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。
数据范围:
−
2
31
<
=
n
<
=
2
31
−
1
-2^{31}<=n<=2^{31}-1
−231<=n<=231−1
即范围为:
−
2147483648
<
=
n
<
=
2147483647
-2147483648<=n<=2147483647
−2147483648<=n<=2147483647
示例1
输入:10
返回值:2
说明:十进制中10的32位二进制表示为0000 0000 0000 0000 0000 0000 0000 1010,其中有两个1。
示例2
输入:-1
返回值:32
说明:负数使用补码表示 ,-1的32位二进制表示为1111 1111 1111 1111 1111 1111 1111 1111,其中32个1
2 答案
自己写的不对,补码不知道该如何处理
class Solution:
def NumberOf1(self , n: int) -> int:
# write code here
if n == 0: return 0
res = 0
is_zheng = True
if n < 0:
n = -n
is_zheng = False
while n:
if n > 1:
res += n % 2
n >>= 1
else:
n -= 1
res += 1
return res if is_zheng else 32 - res
官方解
- 循环按位比较法
我们可以检查该数字的二进制每一位是否为1,如果遍历二进制每一位呢?可以考虑移位运算,每次移动一位就可以。至于怎么统计到1呢?我们都只知道数字1与数字相位与运算,其实只是最后一位为1就是1,最后一位为0就是0,这样我们只需要将数字1移位运算,就可以遍历二进制的每一位,再去做位与运算,结果为1的就是二进制中为1的。
class Solution:
def NumberOf1(self , n: int) -> int:
res = 0
#遍历32位
for i in range(32):
if (n & 1 << i) != 0: # 将1左移i位,再做按位与运算
res += 1
return res
- 位运算优化法
有一个性质: n & ( n − 1 ) n \&(n-1) n&(n−1)会将n的二进制中最低位由1变成0
我们可以不断让当前的 n与 n−1做位与运算,直到 n 的二进制全部变为 0 停止。因为每次运算会使得 n 的最低位的 1 被翻转成0,因此运算次数就等于 n 的二进制位中 1 的个数,由此统计1的个数。
- step 1:使用循环检查n是否为0.
- step 2:不为0就与n−1做位与运算,去掉二进制最后一位的1,并统计次数。
class Solution:
def NumberOf1(self , n: int) -> int:
res = 0
#负数转换
if n < 0:
n &= 0xffffffff
#当n为0时停止比较
while n:
n &= n - 1
res += 1
return res
https://www.nowcoder.com/share/jump/9318638301698411553809
python 负数转换的原因
Python中为什么可以通过bin(n & 0xffffffff)来获得负数的补码? - 若临长风的回答 - 知乎
https://www.zhihu.com/question/314455297/answer/613321568