博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
求整数的二进制表示中1的个数 (转)
阅读量:5243 次
发布时间:2019-06-14

本文共 1703 字,大约阅读时间需要 5 分钟。

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

输入:输入可能包含多个测试样例。对于每个输入文件,第一行输入一个整数T,代表测试样例的数量。对于每个测试样例输入为一个整数。n保证是int范围内的一个整数。 
输出:对应每个测试案例, 输出一个整数,代表输入的那个数中1的个数。
样例输入:
345-1
样例输出:
1232
 
这个题目前面在微软的编程之美上面就看过,今天在九度上面又碰到了。很多题目看着简单,自己写起来就不是这么容易啊。特别是正整数的还好,负整数的我竟然没有写出来。
首先考虑正整数,对于一个a,如果能够被2整除,说明该位为0,不能够被2整除,该位就为1,这样就能很快计算出1的个数。
while(a){
if(a%2!=0)
count++;
a=a/2;
}
但是除法的效率比较低,其实可以将a与1做&操作,可以判断a的最低位是否为1,然后将a依次右移,判断每一位是否为1,效率显然高点。因为移位操作比除法效率高多了。
while(a){
if(a&1==0)
count++;
a=a>>1;
}
但是这个算法还是存在问题,正整数可以,负整数就不行了。当输入的a是一个负数时,不但不能得到正确的1的个数,还将导致死循环。以负数0x80000000为例,右移一位的时候,并不是简单地把最高位的1移到第二位变成0x40000000,而是0xC0000000。这是因为移位前是个负数,仍然要保证移位后是个负数,因此移位后的最高位会设为1。如果一直做右移运算,最终这个数字就会变成0xFFFFFFFF而陷入死循环。为了避免死循环,我们可以不右移输入的数字a。首先a和1做与运算,判断a的最低位是不是为1。接着把1左移一位得到2,再和a做与运算,就能判断a的次高位是不是1……这样反复左移,每次都能判断a的其中一位是不是1。基于此,我们得到如下代码:
int NumberOf1_Solution2(int a) {          int count = 0;          unsigned int flag = 1;          while(flag)          {                 if(a & flag)                         count ++;                 flag = flag << 1;         }          return count; }

另外一种思路是如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减去1,那么原来处在整数最右边的1就会变成0,原来在1后面的所有的0都会变成1。其余的所有位将不受到影响。举个例子:一个二进制数1100,从右边数起的第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成1,而前面的1保持不变,因此得到结果是1011。 我们发现减1的结果是把从最右边一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000。也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0。那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。 这种思路对应的代码如下:

int NumberOf1_Solution3(int i)  {         int count = 0;        while (i)         {                  ++ count;                 i = (i - 1) & i;         }         return count; }

 

扩展:如何用一个语句判断一个整数是不是二的整数次幂? PS:n&(n-1)==0;//二进制数只有一位位1,则该数是2的整数次幂.

转载于:https://www.cnblogs.com/happykoukou/p/5330129.html

你可能感兴趣的文章
最后几本书,不珍藏了。
查看>>
Js时间处理
查看>>
Java项目xml相关配置
查看>>
按钮实现A标签新窗口打开(不用window.open)
查看>>
三维变换概述
查看>>
第三次作业
查看>>
Python的classmethod和staticmethod区别
查看>>
Ubuntu12.04 英文环境下使用ibus输入中文并自动启动输入法
查看>>
SpringMVC 拦截器HandlerInterceptor(一)
查看>>
mvc知识应用
查看>>
数据结构之排序三:插入排序
查看>>
Class.forName(),classloader.loadclass用法详解
查看>>
vue route 跳转
查看>>
Source Insight常用快捷键及注释快捷键设置
查看>>
基于tiny4412的Linux内核移植(支持device tree)(一)
查看>>
Device Tree Usage
查看>>
Python基础【day02】:字符编码(一)
查看>>
sample
查看>>
React 深入学习:ReactCreateRef
查看>>
Python: NumPy, Pandas学习资料
查看>>