每日一题之二进制下1的个数

题目:
输入一个整数n,输出这个整数二进制下1的个数。
读入样例:
13
输出:
3
解释:
13二进制下是1101,一共3个1。

看到这道题,首先应考虑到:
n是一个整数,而不是正整数,因此,读入一个数字进来以后,第一件事就是应该将它变成它的绝对值。
之后来考虑如何把它二进制下1的个数求出来。

思路1:
短除法。来看这样一个例子:

13/2=6……1 6 /2=3……0 3 /2=1……1 1 /2=1……1 倒着数上来,就是1101,也就是13二进制下的每一位。

while (n!=0)
{
sum+=n%2;
n/=2;
}
思路2:
在思路1的基础上,n%2实际上就是看n的二进制下第一位是不是1,那么让n和0000001这个二进制数做一次与运算一样可以得到。
计算机中,位运算的速度要快于四则运算,因此,可以把n%2改成n&1。
同样的道理,n/=2可以改成n>>1。
while (n!=0)
{
sum+=n&1;
n>>1;
}
思路3:
对于这个题目,我们只关心它二进制是1的位置,但使用短除法,依旧没有脱离枚举算法,不是很高效,有没有更快的办法可以不枚举就找到它二进制下每一个为1的位呢?
看这样一个例子:
13=1101,13-1=12=1100,13&12=1100=12,相当于把第一个1消除掉了
12=1100,12-1=11=1011,12&11=1000=8,相当于把的第二个1消除掉了
8=1000,8-1=7=0111,8&7=0000=0,相当于把8的第三个1消除掉了
一共只进行了3次这样的操作,就把n二进制下所有的1都找了出来。
这样做的原因在于,给一个数字减1,就相当于把它从右向左第一个是1的位变成了0。这个位置左边的数都没有改变,右边的全部变成了1。
此时,把它和本来的那个数进行与操作,因为本来的数字这一位右边全是0,因此,这一位右边与操作以后,一定全是0,而这一位一个是1,一个是0,必然是0,而这一位的左边,本来是多少就还是多少。相当于把这个数字二进制下最右边的1给消除掉了。

while (n!=0)
{
sum++;
n = (n-1)&n;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值