二进制中1的个数

二进制中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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值