Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight).
For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011
, so the function should return 3.
Credits:
Special thanks to @ts for adding this problem and creating all test cases.
分析:给定int型整数n,判断n的二进制形式中1的个数。
在分析的时候总共有2种实现方法。
方法一:n转化成二进制字符串,然后遍历字符串中字符为1的个数。在leetcode上提交通过。但是效率不高。
/*提交通过*/
public int hammingWeight1(int n) {
String binary = Integer.toBinaryString(n);
int result=0;
for(int i=0;i<binary.length();i++){
char ch=binary.charAt(i);
if(ch=='1'){
result++;
}
}
return result;
}
方法二:
step1:判断n是否为0;为0则结束,否则转step2;
step2:n与1进行位与操作,如果结果为1则c++;
Step3:n>>>=1(n逻辑右移一位)
/*提交通过*/
public int hammingWeight2(int n) {
int c=0;
while(n!=0)
{
if((n&1)==1)
c++;
n>>>=1;//注意这个地方要用n>>>=1逻辑右移,不可以用n>>=1的算数右移(如果用了算数右移,可能会进入死循环,当输入是负数的时候)
}
return c;
}
方法三:
/*
* n&(n-1)的结果是把n最右边的1变成0,这样循环的次数就是n中1的个数
*/
public int hammingWeight3(int n) {
int count = 0;
while (n!=0) {
count++;
n = (n-1)&n;//1101&1100=1100
}
return count;
}
方法四:针对方法二进行改变,不让n右移,相反的选择一个标志位flag=1让其逐步左移,统计1的个数。
public int hammingWeight4(int n) {
int count = 0;
int flag = 1;
while (flag!=0) { //整个循环的次数等于整数二进制的位数
if((n&flag)!=0){
count++;
}
flag = flag << 1;//每次让flag左移一位。
}
return count;
}
需要明白java对数的右移运算。java分为逻辑右移和算术右移。因为题目的给的是无符号数,并且是要计算其中1的个数,所以用到的是逻辑右移。
比如一个有符号位的8位二进制数11001101,逻辑右移就不管符号位,如果移一位就变成01100110。算术右移要管符号位,右移一位变成10100110。
逻辑左移=算数左移,右边统一添0
逻辑右移,左边统一添0
算数右移,左边添加的数和符号有关,如果是正数则左边添加的全是0,否则添加的全是1.
e.g:1010101010,其中[]位是添加的数字
逻辑左移一位:010101010[0]
算数左移一位:010101010[0]
逻辑右移一位:[0]101010101
算数右移一位:[1]101010101
在看《剑指offer》这本书的时候发现了后两种更好的解法。
上面的四种方法综合比较得知最好的是第三种方法利用n&(n-1)。