剑指Offer-二进制中1的个数

题目:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。例如把9表示成二进制是1001,有2位是1。因此如果输入9,该函数输出2。
1)可能引起死循环的解法:先判断整数二进制表示中最右边一位是不是1。接着把输入的整数右移一位,此时原来处于从右边数起的第二位被移到最右边了,再判断最右边的数是不是1,用(n&1)判断。这样每一次移动一位,直到整个整数变成0为止。

int NumberOf1(int n)
{
   int count = 0;
   while(n) {
       if(n & 1)  
          count++;
       n = n >> 1;      //移位运算比除法的效率要高
   }
   return count;
}

如果处理的是一个负数,比如0x80000000,把负数0x80000000右移一位的时候,并不是简单地把最高位的1移到第二位变成0x40000000,而是0xC0000000,这是因为移位前是个负数,仍然要保证移位后是个负数,因此移位后的最高位会设置为1。如果一直做右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环。

思考:我们就会想,如果输入的数n不移动,那我们就左移1。
解法二:具体思路:首先把n和1做与运算,判断n的最低位是不是1。接着把1左移一位得到2,再和n做与运算,就能判断n的次低位是不是1……,这样反复左移,每次都能判断其中是不是1。这个解法中循环的次数等于整数二进制的位数,32位的整数需要循环32次。

int NumberOf1(int n)
{
   int count = 0;
   unsigned int flag = 1;
   while(flag)
   {
       if(n & flag)
          count ++;
       flag = flag << 1;
   }
   return count;
}

*最好的解法:“整数中有几个1就只需要循环几次。*
具体分析:把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制表示中有多少个1,就可以进行多少次这样的操作。

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

相关题目:
1)用一条语句判断一个整数是不是2的整数次方。一个整数如果是2的整数次方,那么它的二进制表示中有且只有一位是1,而其他所有位都是0.根据前面的分析,把这个整数减去1之后再和它自己做与运算,这个整数中唯一的1就会变成0。

2)输入两个整数m和n,计算需要改变m的二进制表示中的多少位才能得到n。比如10的二进制表示为1010,13的二进制表示为1101,需要改变1010中的3位才能得到1101。我们可以分为两步解决这个问题:第一步求这两个数的异或,第二步统计异步结果中1的位数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值