面试题15:二进制中 1 的个数
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 写成二进制是 1001,有 2 位是 1 。因此,如果输入 9,结果应该输出 2 。
解法一:常规思路
每次判断该数的二进制形式的最后一个数是不是1(让这个数跟1做与操作),判断完后,该数做无符号右移。
public static int solve1(int n) {
int count = 0;
int flag = 1;
while(n != 0) {
if((n & flag) > 0) {
count++;
}
n = n >>> 1;
}
return count;
}
解法二:魔鬼思路
- 假设这个数的最后一位是1,那么当这个数减1时,最后一位变成0,其他位不变。
- 假设这个数最后一位不是1,而是在中间某一位,则该数减1后,后面所有位位1,前面所有位保持不变。
- 所以,让 n = n & (n-1),每次可以消除该数中的一个1,当所有1都消掉以后,该数为0。
public static void solve2(int n) {
int count = 0;
while(n != 0) {
count++;
n = n & (n-1);
}
return count;
}
相关题目
- 用一条语句判断一个整数是不是 2 的整数次方。一个整数如果是 2 的整数次方,那么它的二进制表示中有且只有一位是 1,而其他所有位都是 0 。根据前面的分析,把这个数减 1 再和这个数做与操作,如果这个数变成 0 的话,说明这个整数是 2 的整数次方。
- 输入两个整数 m 和 n,计算需要改变 m 的二进制表示中的多少位才能得到 n 。比如 10 的二进制表示为 1010,13 的二进制表示为 1101,需要改变 1010 中的 3 位才能得到 1101。我们可以分为两步解决这个问题:第一步求这两个数的异或;第二步统计异或结果中 1 的位数。
举一反三
把一个整数减去 1 之后再和原来的整数做位与运算,得到的结果相当于把整数的二进制表示中最右边的 1 变成 0。很多二进制的问题都可以用这种思路解决。