剑指offer编程题 -- 二进制中1的个数

题目描述:

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

注意:整数在计算机中本身就是以二进制形式存储的。

主要使用的是位运算。

补码的移位:

左移:正负数均是在右边补0;

右移:正数是在左边补0,负数是在左边补1。

 

方案1:

依次将1左移,与该数做&运算。

class Solution {

public:

     int  NumberOf1(int n) {

         int count = 0;

         int tmp = 1;

         while(tmp){

             if(n & tmp){

                 count++ ;

             }

             tmp = tmp << 1;

         }

         return count;

     }

};

运行时间:4ms

占用内存:480K

方案2:该数与1做&运算,但要注意循环条件,因为当为负数时,负数右移左边补1,所以可能陷入无限循环,因此需要控制其位数。该方案需要一共执行判断32次。

class Solution {

public:

     int  NumberOf1(int n) {

         int count = 0;

         int tmp = 0;

         while(tmp < 32){

             if(n & 1){

                 count++ ;

             }

             n = n >> 1;

             tmp++;

         }

         return count;

     }

};

运行时间:3ms

占用内存:384K

方案3:x&(x-1)可以将整数的最右边的1变为0,根据这个,我们只需循环判断x = x&(x-1) 是否为0,即可统计1的个数。该方案相比方案2而言减少了循环的次数。

 

 

eg:-5二进制中1的个数。

x

x&(x-1)

0101

0101 & 0100 = 0100

0100

0100 & 0011 = 0000

 

class Solution {

public:

     int  NumberOf1(int n) {

         int count = 0;

         while(n){

             count++;

             n = n & (n-1);

         }

         return count;

     }

};

运行时间:3ms

占用内存:480K

 

方案4:使用辗转相除法。

注意:该方案只能用于正数,不能用于负数。

eg: -1 % 2 != 1,count =0;但实际上-1的二进制中有32个1。

class Solution {

public:

     int  NumberOf1(int n) {

         int count = 0;

         while(n){

           if(n % 2 == 1){

              count++;

}

           n = n/2;

}

     

         return count;

     }

};

参考链接:

http://www.cnblogs.com/AndyJee/p/4630568.html

https://blog.csdn.net/zhao_miao/article/details/79747664

 

 

猜你喜欢

转载自blog.csdn.net/mmg188/article/details/88182256