位1的个数
这道题出自LeetCode,题目如下:
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为汉明重量)。
示例1 :
输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
示例2 :
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
示例3 :
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
这道题的意思很简单,而且有一种在O(1)时间内计算出结果的巧妙解法。要想统计位1的位数,我们可以利用分而治之的思想进行考虑,就是先去统计前16位中1的位数和后16位中1的位数,然后求和即可。类似地,就要先去统计每8位中1的位数,最后划分到最小单位,就是去统计每1位中1的位数然后求和。统计每1位的1的位数很简单,只要看它是否为1即可,为1数量就是1,否则就是0。至于求和,我们注意到,两个1位数之和最多只会是2,而2的二进制表示是10,用两位足够表达,所以直接相加即可。相加之后的结果,就是每2位中保存了这2位中1的数量。以此类推,可以得到每4位中1的数量,每8位中1的数量,一直到最后32位中1的数量,也就是最终答案。通过的代码如下所示:
class Solution {
public:
int hammingWeight(uint32_t n) {
const uint32_t M1 = 0x55555555; // 01010101010101010101010101010101
const uint32_t M2 = 0x33333333; // 00110011001100110011001100110011
const uint32_t M4 = 0x0f0f0f0f; // 00001111000011110000111100001111
const uint32_t M8 = 0x00ff00ff; // 00000000111111110000000011111111
const uint32_t M16 = 0x0000ffff; // 00000000000000001111111111111111
n = ((n >> 1) & M1) + (n & M1);
n = ((n >> 2) & M2) + (n & M2);
n = ((n >> 4) & M4) + (n & M4);
n = ((n >> 8) & M8) + (n & M8);
n = ((n >> 16) & M16) + (n & M16);
return n;
}
};