题目描述
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
思路分析
方法一、计算每一位是否为 1
显然,我们可以通过判断数中每一位是否为 1 求得位 1 的个数。
① 获得最低位是否为 1,通过 n & 1,若结果为 1 ,说明最低位为 1,否则最低位为 0。
② 通过位移更新最低位, n >>= 1,移位 32 次后,n 中的每一位都会被获得。
public class Solution {
public int hammingWeight(int n) {
int count = 0;
for (int i = 0; i < 32; i++) {
count += n & 1;
n >>= 1;
}
return count;
}
}
方法二、n & (n - 1) 去掉二进制中的最后一位 1,直至 1 全部去除
例如 n = 20,n - 1 = 19。从十进制的角度来看,相当于 20 中的最后一位 1 借给后两位来减 1。
这就导致图中圈出的部分各位完全相反。
因此,两数相与后, 20 的最后一个 1 就被敲掉了。
public class Solution {
public int hammingWeight(int n) {
int count = 0;
while (n != 0) {
n &= (n - 1);
count++;
}
return count;
}
}
方法三、n ^ ((-n) & n) 去掉二进制中的最后一位 1,直至 1 全部去除
例如 n = 20,20 的二进制表示为 0001 0100,而 -20 的二进制表示 1110 1100
正是因为 -n 为 n 按位取反加 1 再补齐后的值,将 n 和 -n 进行与运算,将得到只包含 n 的最后一位 1 的数。
去除 n 的最后一位 1 可以异或处理 :n ^ ((-n) & n)
public class Solution {
public int hammingWeight(int n) {
int count = 0;
while (n != 0) {
n ^= (-n) & n;
count++;
}
return count;
}
}
当然,通过两数相减的方式也是可以的:n - ((-n) & n)
public class Solution {
public int hammingWeight(int n) {
int count = 0;
while (n != 0) {
n -= (-n) & n;
count++;
}
return count;
}
}