剑指offer——二进制中1的个数

二进制中1的个数

输入一个整数,输出该数二进制表示中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;
    }
}

  

posted @ 2018-03-08 09:36  SkyeAngel  阅读(153)  评论(0编辑  收藏  举报