剑指 Offer 15. 二进制中1的个数 - leetcode 剑指offer系列

题目难度: 简单

原题链接

今天继续更新剑指 offer 系列, 这道题很经典, 大家可能已经熟悉两种方法了, 这里额外提供两种方法 🤩 供大家参考~

老样子晚上 6 点 45 分准时更新公众号 每日精选算法题, 大家记得关注哦~ 另外在公众号里回复 offer 就能看到剑指 offer 系列当前连载的所有文章了

题目描述

请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9  表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。

题目样例

示例 1

输入

00000000000000000000000000001011

输出

3

解释

输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。

示例 2

输入

00000000000000000000000010000000

输出

1

解释

输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。

题目思考

  1. 可以使用哪些位运算?
  2. 不用位运算可以吗?

解决方案

方案 1 & 2 - 直接统计 1 的个数

分析
  • 最直观的思路就是直接统计二进制数字里 1 的个数
实现
  1. 方案 1: 转成二进制字符串统计’1’的个数
  2. 方案 2: 移位, 根据最低位是否为 1 来统计. 注意题目是 32 位整数, 所以限制移位次数为 32 次, 避免负数的高位一直为 1 即可
复杂度
  • 时间复杂度 O(logN)
    • 数字 N 的位数为logN, 需要遍历这么多次
  • 空间复杂度 O(1)
    • 只使用了几个变量
代码
方案 1: 转二进制字符串统计 1
class Solution:
    def hammingWeight(self, n: int) -> int:
        # 方法1: 转二进制字符串统计1
        return bin(n).count('1')
方案 2: 循环移位统计 1
class Solution:
    def hammingWeight(self, n: int) -> int:
        # 方法2: 循环移位统计1
        res = 0
        for i in range(32):
            if n == 0:
                break
            res += n & 1
            n >>= 1
        return res

方案 3 & 4 - 利用位运算统计 1 的个数

分析
  • 如果我们能直接定位到 1, 然后每次都把已经统计的 1 排除掉的话, 就只需要操作 1 的个数次, 而不需要遍历所有位了
实现
  1. 方案 3: 利用 n & (n-1). 大家可以想象一下 n-1 在二进制上所做的操作: 其实就是把 n 的最低一位的 1 转成 0, 然后后面的 0 都转成 1, 高位保持不变, 这样它们的 & 值自然就会去掉最低位的 1. 这样循环操作, 最终就会去掉所有 1, 得到 0, 操作的次数也即 1 的个数了.
  2. 方案 4: 利用 n & -n. 熟悉树状数组的同学可能会比较清楚这个表达式, 这个就是 lowbit. 通俗点说它相比 n, 只保留最低位的 1, 其他位全清 0. 这个同样可以根据 -n 的二进制含义得出, 补码与原数的 & 的结果会正好只留最低位的 1. 然后将 n 减去这个 lowbit, 就等于去掉了一个 1, 循环最终会得到 0, 操作的次数也即 1 的个数了.
复杂度
  • 时间复杂度 O(M)
    • 设数字有 M 位 1, 需要遍历这么多次
  • 空间复杂度 O(1)
    • 只使用了几个变量
代码
方案 3: n &= n - 1
class Solution:
    def hammingWeight(self, n: int) -> int:
        # 方法3: n &= n - 1
        res = 0
        while n:
            n &= n - 1
            res += 1
        return res
方案 4: n -= n & -n
class Solution:
    def hammingWeight(self, n: int) -> int:
        # 方法4: n -= n & -n
        res = 0
        while n:
            n -= n & -n
            res += 1
        return res

大家可以在下面这些地方找到我~😊

我的知乎专栏

我的 CSDN

我的 Leetcode

我的牛客网博客

我的公众号: 每日精选算法题, 欢迎大家扫码关注~😊

每日精选算法题 - 微信扫一扫关注我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值