二进制中1的个数

题目描述

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

解题思路

首先需要注意,负数的补码是其反码加1(符号位为1),将负数转化为相应正数的想法是不可行的,因为它们的二进制补码是不一样的(不仅是符号位不同)。


然后需要注意,每次判断该整数的最后一位是否为1,然后将该整数右移一位的想法也是不可行的。因为有符号数的移位是算术移位,而不是逻辑移位。这意味着,每次移位后的符号位都是不变的,所以对一个负数进行移位将永远不可能变成0。


要解决这个问题,有两种方法。第一种方法是定义一个无符号数flag,初始化为1,每次向左移动一位。这样,flag就每次都是一个第i位为1而其他位为0的整数。用这个flag与整数n进行位与,从而判断n的第i位是否是1。这样对flag移位而不是对n移位,就避免了对负数进行移位将导致的死循环问题。需要注意,只有令flag为无符号数,才可以通过逻辑移位使得flag=1000...0。


第二种方法,对于一个整数n,如果n不为0,则n&(n-1)将使得n最低位的1变为0,而高位保持不变。因此,当n不为0时,每次将n&(n-1)的结果赋给n,并加以记录,直到n变成0。这样,就可以记录n总共有几位1了。需要注意的是,当n为INT_MIN(1000.....0)时,n-1将得到INT_MAX(0111....1),n(n-1)=0,总共有1个1。因此,n=INT_MIN的情况也不用单独拿出来判断。


代码

class Solution {
public:
     int  NumberOf1(int n) {
         //方法一
         /*
         int count = 0; //记录1的个数
         unsigned int flag = 1; //用于查看1的个数,必须用无符号数
         
         while (flag > 0) //移动flag而非n
         {
             if (n & flag) //按位与
                 count++;
             
             flag <<= 1;
         }
         
         return count;
         */
         
         //方法二
         //if (n == INT_MIN) //最小值是1000...
             //return 1;
         
         int count = 0;
         while (n != 0) //有负数
         {
             count++;
             n = n & (n - 1); //将最低位1去掉
         }
         
         return count;
     }
};



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值