输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
public class Solution { public int NumberOf1(int n) { } }
在java中 int型是以32位存在的
1依次左移,& n,但是要移动32次
注意判断条件是:n & flag != 0
因为flag是2的倍数增长,1 2 4 8 16 所以,n & flag 的话也是 1 2 4 8 等某一位为1或者0 即 0000 0010 0000 0010 0000 0001 0000 1100 & 1000 所得的结果为8
而 & 0010的话,所得结果为0
public class Solution { public int NumberOf1(int n) { if(n == 0) return 0; int flag = 1; int count = 0; for(int i = 0; i < 32; i++){ if((n & flag) != 0){ count++; } flag = flag << 1; } return count; } }
比较简单的方法:n右移,& 1,看结果,计算机内部正负数都以补码表示,无符号右移 >>>1
正数的左移和右移,负数的无符号右移 相应的补码右移,最高位补0
负数的右移:补码的高位补1,然后按位取反+1
public class Solution { public int NumberOf1(int n) { if(n == 0) return 0; int count = 0; while(n != 0){ if((n & 1) == 1){ count++; } n = n >>> 1; } return count; } }
最简单的方法(有多少个1,则进行多少次循环):
若n不为0,则 n 至少有一位是1,n-1的话,是最右边的1变为0,这个1后面的0都变为1,其余的则不变
用n与n-1在二进制之间,只在n的最右边的1变为了0,右边的0都变为了1,例如12的1100,而11则为1011,他们之间在第三位之前的1都没变,只有12的最右边的1往后都取反了,若12 & 11,则第三位之前的不变,其余的变为0,再依次减一,相与
12 & 11 --> 1100 & 1011 ==>1000(8)
8 & 7 --> 1000 & 0111 ==> 0000(0) 循环结束
负数:
-9 & -10 --> 0111 & 0110 ==> 0110(-10)
-10 & -11 --> 0110 & 0101 ==> 0100(-12)
-12 & -13 --> 0100 & 0011 ==> 0000(0) 循环结束
public class Solution { public int NumberOf1(int n) { if(n == 0) return 0; int count = 0; while(n != 0){ n = n & (n - 1); count++; } return count; } }