编写一个函数可以计算无符号整数中位 1 的个数(即汉明重量)。
例一:
输入: 00000000000000000000000000001011
输出: 3
解释: 输入的二进制字符串 00000000000000000000000000001011 共有 3 个位 1。
例二:
输入: 00000000000000000000000010000000
输出: 1
解释: 输入的二进制字符串 00000000000000000000000010000000 共有 1 个位 1。
例三:
输入: 11111111111111111111111111111101
输出: 31
解释: 输入的二进制字符串 11111111111111111111111111111101 共有 31 个位 1。
提示:
1. 在某些语言中,比如 Java,不存在无符号整数类型。这种情况下,给定的输入将会是有符号整数类型,但这应该对你的实现没有影响,因为有符号或无符号实际上的二进制表示形式是一样的。
2. 在 Java 中,编译器使用二进制补码来表示有符号整数。因此,在例三中的输入表示的有符号整数为 -3
。
二进制数中 1 的个数这个问题可以说是很常见的基础问题了。
最简单最慢的方法就是转换成字符串查 1 的数量。比较快的方法是使用位运算。
举例来说,整数 35
,用二进制表示就是 0010 0011
,二进制数中有 3 个 1。计算这个数字中的 1 的个数,使用与运算便可以快速完成。
这里有个位运算的小知识,n & (n-1)
可以消去二进制数的最右边的 1。比如 35 & 34
:
0010 0011
0010 0010
---------
0010 0010
结果得到 34
,接下来 34 & 33
:
0010 0010
0010 0001
---------
0010 0000
结果得到 32
,接下来 32 & 31
:
0010 0000
0001 1111
---------
0000 0000
结果得到 0
,计算过程便完成了。
在得到 0
之前,一共计算了 3 次,也就是说一共消去了 3 个 1。即,给定数字 35
,得出结果为 3
。
使用 C 语言表示以上算法:
int hammingWeight(uint32_t n) {
if (!n)
return 0;
uint8_t sum;
for (sum = 0; n; sum++) {
n &= (n - 1);
}
return sum;
}