191. 位1的个数

难度:简单 | 主题:位运算

题目

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。

示例

 
输入:n = 11(二进制 1011)
 
输出:3
 

思路

先讲个故事:灭灯游戏

一排灯泡,有的亮(1)有的灭(0)。你要数有多少盏亮着的灯。你不会一盏盏查——你用一个技巧:每次按一下开关,把最右边的亮灯灭掉。按几次灭完,就有几盏灯亮过。

n & (n-1) 就是”灭掉最右边那盏亮灯”的魔法操作。


引导式推导:n & (n-1) 的魔力

n & (n-1) 把最低位的 1 变成 0。每次消去一个 1,消完为止。


graph LR

    A["n = 11010"] -->|"n-1 = 11001"| B["n & (n-1) = 11000"]

    B -->|"n-1 = 10111"| C["n & (n-1) = 10000"]

    C -->|"n-1 = 01111"| D["n & (n-1) = 00000"]

    D --> E["count = 3"]

原理:n-1 会把 n 最低位的 1 变成 0,该位后面的所有 0 变成 1。n & (n-1) 后,最低位 1 及其后面的位全部归零。

方法时间空间
n & (n-1)O(k)(k 为 1 的个数)O(1)
逐位检查O(32)O(1)
bin(n).count('1')O(log n)O(log n)

代码

 
def hammingWeight(self, n):
 
    count = 0
 
    while n:
 
        n &= (n - 1)
 
        count += 1
 
    return count
 

复杂度

指标解释
时间O(k)k 为二进制中 1 的个数,每次循环消除一个 1
空间O(1)只用了常数个变量

实战考量

频率分析

出现在:位运算经典题。考察 n & (n-1) 技巧,是常客。字节/美团常考。

延伸思考

Q:n & (n-1) 为什么能消除最低位 1?

A:以 n=12 (1100) 为例:n-1=11 (1011),n & (n-1) = 1000。n-1 把最低位 1 变 0、后面的 0 全变 1,& 操作后最低位 1 及后面的位全部归零。

Q:如果不用 n & (n-1),逐位检查怎么做?

A:for i in range(32): count += n & 1; n >>= 1。O(32) 固定,不如 n & (n-1) 灵活。

Q:n & (n-1) 还有哪些应用场景?

A:(1) 判断 2 的幂:n & (n-1) == 0(231 题);(2) 计算汉明距离:x ^ y 后统计 1 的个数。

易错点

  • while n 而非 while n > 0(处理 n 被当负数的情况)

  • n & (n-1) 的括号不能漏


生活类比

n & (n-1) → 灭灯计数

一排灯泡亮着,你每按一次开关就灭掉最右边那盏亮灯。数按了几次,就是亮灯总数。n & (n-1) 就是那个”精准灭最右亮灯”的开关。


相关题目

题目关系
231-2的幂n & (n-1) == 0 同族技巧
136只出现一次的数字异或位运算

→ 返回题单:LeetCode学习路线图 > 十四、数学与位运算

速记卡(面试闪卡)

Q1:一句话讲清「191. 位1的个数」到底是什么?

A:数一个无符号整数二进制表达里,有多少个比特是 1。

Q2:思路:n&(n-1) 灭最右亮灯 —— 怎么理解?

A:一排灯泡亮着,每按一次开关就灭掉最右边那盏亮灯——n & (n-1) 就是这魔法开关。位运算(Bit Manipulation)把最低位 1 清零,按几次就是几盏灯。

Q3:代码:循环清零计数 —— 怎么理解?

A:while n: n &= (n-1); count++。每次消去一个 1,消完 n 变 0 循环停。汉明重量(Hamming Weight)就这一行搞定,干净利落。

Q4:复杂度:时间与空间 —— 怎么理解?

A:只跟 1 的个数 k 有关,时间复杂度(Time Complexity)O(k) 精准打击;空间复杂度(Space Complexity)O(1) 不占地,比逐位扫 32 次更灵。

Q5:生活类比:灭灯计数游戏 —— 怎么理解?

A:位 1 的个数(Number of 1 Bits)像灭灯游戏:亮灯是 1、灭灯是 0,每次精准灭最右亮灯(Bit Manipulation),数按了几次开关就是答案。

Q6:核心速记主线有哪些?

  • n&(n-1) 消最低位 1

  • 循环几次就有几个 1

  • 时间 O(k) 空间 O(1)

  • 还能判 2 的幂

口诀

A:亮灯几盏数一数,

n&(n-1) 灭右珠。

循环几次灯皆无,

位运算里藏妙术。

相关链接