【剑指offer】JZ15 二进制中1的个数

1 问题

输入一个整数 n ,输出该数32位二进制表示中1的个数。其中负数用补码表示。

数据范围: − 2 31 < = n < = 2 31 − 1 -2^{31}<=n<=2^{31}-1 231<=n<=2311
即范围为: − 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就是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
  1. 位运算优化法

有一个性质: n & ( n − 1 ) n \&(n-1) n&(n1)会将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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LouHerGetUp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值