一.任务描述:
给定一个正整数 n,编写一个函数,获取一个正整数的二进制形式并返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。
示例 1:
**输入:**n = 11
**输出:**3
解释: 输入的二进制串 1011
中,共有 3 个设置位。
示例 2:
**输入:**n = 128
**输出:**1
解释: 输入的二进制串 10000000 中,共有 1 个设置位。
示例 3:
**输入:**n = 2147483645
**输出:**30
解释: 输入的二进制串 1111111111111111111111111111101 中,共有 30 个设置位。
二.解题思路:
**逐位检查法:**遍历整数的每一位,检查该位是否为1
》时间复杂度:O(k),其中k为整数位数(对于32位整数为O(32))
》空间复杂度:O(1)
三.代码实现:
C
int hammingWeight(int n) {
int ret = 0;
for (int i = 0; i < 32; i++) {
if (n & (1u << i)) {
ret++;
}
}
return ret;
}
四.优化方向:
分治法(并行计算)
C
int hammingWeight_parallel(int n) {
// 第一步:每2位一组,统计1的个数
// 01 -> 01 (二进制表示1的个数)
n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
// 第二步:每4位一组,统计1的个数
n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
// 第三步:每8位一组,统计1的个数
n = (n & 0x0F0F0F0F) + ((n >> 4) & 0x0F0F0F0F);
// 第四步:每16位一组,统计1的个数
n = (n & 0x00FF00FF) + ((n >> 8) & 0x00FF00FF);
// 第五步:每32位一组,统计1的个数
n = (n & 0x0000FFFF) + ((n >> 16) & 0x0000FFFF);
return n;
}
五.总结:
核心技巧:
-
位运算技巧 :
n & (n-1)消去最低位的1是核心技巧之一 -
并行计算:通过分治思想,将统计1的个数分解为多个小问题并行解决
-
空间换时间:查表法通过预计算结果来加速实际计算