题目描述
给定一个 32 位有符号整数,返回它二进制表示中 1 的个数。
负数使用 补码 表示。
思路速览
方法 | 时间复杂度 | 空间复杂度 | 特点 |
|---|---|---|---|
位移逐位检验 | O(32) ≈ O(1) | O(1) | 直观,但固定 32 次循环 |
Brian Kernighan 算法 | O(k) k=1 的个数 | O(1) | 推荐 ,循环次数等于 1 的个数 |
Python 内置 bin | O(32) | O(1) | 一行代码,面试通常不让用 |
下面重点讲解 Brian Kernighan 算法(面试最加分)。
Brian Kernighan 算法原理
任何整数
n与n-1做 按位与 会把最低位的 1 变为 0。
例如
n = 1100 (12)
n-1 = 1011 (11)
n&(n-1) = 1000 (8) ← 最低位的 1 被抹掉重复此操作直到 n=0,操作次数 即为 1 的个数。
代码实现
C++ 版本
class Solution {
public:
int NumberOf1(int n) {
int count = 0;
while (n) {
++count;
n = (n - 1) & n; // 抹掉最低位 1
}
return count;
}
};Python 版本(兼容负数)
class Solution:
def NumberOf1(self, n: int) -> int:
count = 0
# 将负数转换为 32 位无符号数
if n < 0:
n = n & 0xffffffff
while n:
count += 1
n = (n - 1) & n
return countPython 一行写法(仅供娱乐)
def NumberOf1(n):
return bin(n & 0xffffffff).count('1')测试用例
输入 | 输出 | 说明 |
|---|---|---|
11 | 3 | 1011 |
-1 | 32 | 补码全 1 |
0 | 0 | 无 1 |
0x80000000 | 1 | 只有符号位为 1 |
复杂度分析
时间复杂度:
O(k),其中k是n中 1 的个数;最坏k ≤ 32。空间复杂度:
O(1),仅使用常数变量。
面试小贴士
负数陷阱:Python 右移负数会保持符号位,需先
& 0xffffffff转无符号。效率对比:Brian Kernighan 算法比逐位位移 循环次数更少,面试官更青睐。
扩展:可推广到统计任意进制中特定数字的出现次数。
结语
掌握位运算技巧是每一位高级程序员的必修课。Brian Kernighan 算法不仅优雅,而且高效,值得在面试与工程实践中反复使用。
如果觉得有帮助,点个 Star ⭐ 再走!
476

被折叠的 条评论
为什么被折叠?



