剑指offer 15 数字中1的个数

先来个简单的进制问题:Excel中,A代表1,AB代表28列,给一个字符串,返回数字。这个题就是转换成26进制做就很简单。
回到本题,其实思路类似于dp,每次判断最后一个是不是1,然后右移即可。注意:右移比你直接/2快很多。

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ret = 0;
        while(n>0)
        {
            if(n&1)ret += 1;
            n >>= 1;
        }
        return ret;
    }
};

接下来请思考虑有符号数,即第一位是1表示负数的情况。如果这样,第一位是不能动的。这种情况怎么做?
答案是不太好想的(或者说我太笨),即我们每次不要右移数字,而是左移比较数1,这样每次就能和左边比较了。统计1的个数不用管是不是符号位,只要用无符号数比较即可。当无符号数溢出时会变成负数(其实是从0开始重新循环,但是表示成负数)。

上述算法和第一种解法是等价的,下面介绍一种更强的算法,即传说中的n&n-1。
我们注意一个数如果最后一位是1,那它-1会让最后一位变0,做与操作后最靠右的1消失。如果最后一位不为0,-1会让最右的一个1右边全变1,1变0.如1100 & 1001 = 1000,所以n&n-1会消去最靠右的一个1. 注意,n-1不用加括号,因为位运算优先级很低,也可以使用 &=,代码如下:

class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ret = 0;
        while(n>0)
        {
            n = n&n-1;
            ret += 1;
        }
        return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值