二进制中1的个数

来源:互联网 发布:淘宝买aj的正品店 编辑:程序博客网 时间:2024/05/16 01:19

二进制中1的个数

输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 —— [ 牛客网 ]

本题要求求解整数二进制数据中1的个数,看到题目的时候,第一想法应该是遍历一遍二进制数,计算总数。即每一次与1之后右移,判断是1则加1。

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

针对正整数而言,这样的算法可以解决问题,但是针对负整数而言,题目说采用的补码形式存储,最高位是1代表负数,例如16位的整形负数-8,补码形式为:1111111111111000。

1111111111111000-->1111111111111100 右移一位1111111111111100-->1111111111111110 右移一位1111111111111110-->1111111111111111 右移一位...

对于负数的右移操作,为保证右移后依然是负数,所以填充的是1,如果按照上面的算法思路,当填充到全1的时候,算法会陷入死循环。
为了避免死循环,我们采用相对位移的方式,既然不能右移整数,那我们左移与运算的1的位置,计算1的个数。

解法一
    class Solution {    public:     int  NumberOf1(int n){          int count = 0;         unsigned int flag = 1;         while(flag){             if(n & flag)count ++;             flag = flag << 1;         }         return count;     }    };

假设我们计算机的整形数据表示是32位的,那么计算一次我们需要计算32次,如果能够直接确定1的位置这样来计算,可以更加快速的得到结果。
例如我们有整数110101,我们将整数减1可得到整数中最末尾的一个1的位置之后的所有为0的数字转换为1,而1之前的数字不变,进一步n&(n-1),即计算了一次1的位置。

110101 - 1 = 110100   110101 & 110100 = 110100   第一个1出现110100 - 1 = 110011   110100 & 110011 = 110000   第二个1出现110000 - 1 = 101111   110000 & 101111 = 100000   第三个1出现100000 - 1 = 011111   100000 & 011111 = 000000   第四个1出现,找到全部的1
解法二
    class Solution {    public:     int  NumberOf1(int n){          int count = 0;         while(n){             count ++;             n = n & (n-1);         }         return count;     }    };

巧妙的转换思维,利用二进制位运算的技巧。

0 0
原创粉丝点击