先来个简单的进制问题: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;
}
};