求一个整数 n 中,二进制表示中1的个数
n & 1
, 先判断 n 中最后一位是不是1,再将 n 右移一位,继续判断。注意到在 java 中,int数据类型固定为 32 位,可以循环判断 32 次,避免负数情况下的死循环
public static int numberOf1(int n) {
int count = 0;
int c = 32;
while (c != 0) {
if ((n & 1) != 0) {
count++;
}
n = n >> 1;
c--;
}
return count;
}
或者让 n 分别与1, 10, 100, 1000, 10000, 100000, 1000000...
做与运算,计算每个位上是否为1
public static int numberOf11(int n) {
int count = 0;
int flag = 1;
while (flag != 0) {
if ((n & flag) != 0) {
count++;
}
flag = flag << 1;
}
return count;
}
超级屌的时间复杂度O(k)的算法
因为 n-1
对二进制数据做的操作为: 从后开始,碰到1,将1变为0,之前的0变为1。相当于找到最开始出现的1,并对1及低位取反。eg:
20 : 10
100
20-1: 10
011
而(n-1)&n
就是取最先出现1的位置之后的高位,eg:(20-1)&20: 10
000
这样,就可以不用循环运算每一位,而能够定位每一个1, 并且不影响后面的结果。
public static int numberOf111(int n) {
int count = 0;
while (n != 0) {
n = (n-1)&n;
count++;
}
return count;
}