剑指offer-第十题方法总结

题目:实现一个函数,输入一个整数,请输出这个数的二进制表示中1的个数。例如:输入5,的二进制是101,有两个1则输出2.

这个题目很简单啊!!!
int count_one( int n)
{
                 int count = 0;
                 while (n)
                {
                                 if (n&1)
                                count++;
                                n=n >> 1;
                }
                 return count;
}


     写出上面的代码是有问题的,如果输入负数,则进行的是算术移位,就会陷入死循环。


     略微思考一下可以将上面这种方法改进一下,整数有32个bit位,分别将这个数的每一位与1按位与,如果为真,则count++。
int count_one( int n )
{
                 int i = 0;
                 int count = 0;
                 for (i = 0; i < 32; i++)
                {
                                count += (( n >>i) & 1);
                }
                 return count;
}

    这样确实能够做出来,对于每一个数,都要判断32次,很麻烦。


      那么有没有一种方法能够使得一个数二进制中有多少个1, 就循环多少次呢???
       答案是有的。

先看看下面这些式子找一找规律:
 1、
10    &    9      =8
1010       1001 =1000

2、
 8     &  7        =0
1000      0111 =0000

3、
 5    &   4    =4
101      100 =100

4、
 4     & 3      =0
100      011  =000

可以发现,n&(n-1)的结果与n相比,其二进制中1的个数少了一个。

根据这样的规律我们可以很容易的实现这道题目的最优解。

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


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值