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

题目描述

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

知识点:

(1)按位与(&)

  两位全为1,结果才为1. 例:0&1=0 1&1=1

  作用:1.清零     2.取一个数中指定数: 例:X=10101110 取X得低四位。 X&00001111=0000 1110

(2)按位或( |)

 只要有一个位1,结果就位1.

 作用:常用来对一个数据的某些位 置1.  例:X=00001001 使X低四位为1 X|0000 1111=00001111

(3)异或(^)

 两个相应位值不同,则该位结果为1,否则为0.

 作用:1.使特定位翻转,找一个数,对应X要翻转的各位,该数的对应位为1,其余位为0,此数与X对应位 异或即可。

        例:X=10101110 使X低四位翻转

     X^0000 1111=10100001

    2.与0相异或,保留自身原值。(应用在两个变量交换值,效率最高)

    例:A=A^B,B=A^B,A=A^B 这样A和B的值就交换了。

(4)取反(~)

对一个二进制数按位取反。~0=1

例:在java中对有符号int型数取反运算。 注:在java中有符号整数都是用补码表示的。

补码的知识:

原码:一个整数按照绝对值大小转换成的二进制数称为原码。

反码:1.正数的反码与其原码相同;2.负数的反码是对其原码逐位取反,但符号位除外。原码10010= 反码11101 (10010,1为符号码,故为负)(11101) 二进制= -2 十进制

补码:补码表示法规定:正数的补码与其原码相同;负数的补码是在其反码的末位加1。

取反方法:1.对正数:先对其表示的二进制取反,得到负数的补码;然后求出反码,最后求出原码。(即为所求数)

     例:~3

       java中int类型的长度是四个字节,也就是32位,so:

              00000000 00000000 00000000 00000011 

        取反:     1...                                         11111100  最高位为1,所以这是负数的补码形式。

        求出反码: 1...                                         11111011

               求出原码:   0...                                         00000100  数字为4

        之前此数的补码最高位为1,所以 ~3=-4

     2.对负数:先求负数的补码,然后直接取反。(注意最高位1代表负数,0代表整数)。

(5)左移(<<)

将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)

例如: 2<<1 =4 10<<1=100

若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

例如:

11(1011)<<2= 0010 1100=22

11(00000000 00000000 00000000 1011)整形32bit

(6)右移(>>)

将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。若右移时舍高位不是1(即不是负数),操作数每右移一位,相当于该数除以2。

左补0还是补1得看被移数是正还是负。

例如:4>>2=4/2/2=1

-14(即1111 0010)>>2 =1111 1100=-4

解题思路:

参考博客:https://www.cnblogs.com/edisonchou/p/4752086.html

1.对操组数右移:整数的最低位和1做与运算,如果结果为1,则这一位是1。然后将这个数右移,继续用该数的第二位和1做与运算判断。但是会存在一个问题。如果是负数的话,一直右移最后这个数会变为全1,然后和1做与一直为True,导致陷入死循环。所以这种方法不可取。

2.那么和1相对应的方法就是操作数不改变,将1不断的左移,和二进制的每一位分别做与运算。这种操作是可取的,不过效率较低,因为二进制的int占32位,所以flag(1)就要分别和这个二进制的32位中的每一位做与运算,才能得到最终的判断,所以需要循环32次。

3.把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

剑指offer:二进制中1的个数_第1张图片

 

代码实现

实现1(低效的)

public class Solution {
    public int NumberOf1(int n) {
        int flag=1;
        int count=0;
        while(flag!=0){
            if((n&flag)!=0){
                count+=1;
            }
            flag=flag<<1;
        }
        return count;
 
    }
}

实现2:

public class Solution {
    public int NumberOf1(int n) {
        int count=0;
        while(n!=0){
            count++;
            n=n&(n-1);
        }
        return count;
 
    }
}

 

你可能感兴趣的:(剑指offer)