标签:min 特点 优化 mingw 移位 测试 精简 strong 比特
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9?表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
测试用例1:
测试用例2:
测试用例3:
首先来分析题目,要统计二进制中1的个数,那么我们首先想到的是 要将此数的每个比特位都要遍历一遍,然后判断为1count++,最后返回count。就写出如下代码
int hammingWeight(uint32_t n) {
int count = 0;
while(n)
{
if(n&1)
count++;
//此处移位时,如果n为负数可能会导致死循环
n >>= 1;
}
return count;
}
上面的代码在统计无符号数时,结果是正确的,但是,在算负数时,可能会导致死循环。
此处我们采用的 位运算 来代替 除法运算,因为计算机中除法的效率要比比移位运算要低得多。我们在实际编程中要尽量地用移位运算符代替乘除法。
再者我们来讨论一下测试用例为负数。右移运算符的特点是,右移n位的时候,最右边的n位将被丢弃。在右移处理最左边位的情形比较复杂。如果数字是一个无符号值,则用0填补最左边的n位;如果数字为有符号数,则用数字的符号位填补最左边的n位。也就是说,如果数字原先是正数,则右移之后在最左边补n个0;如果数字原先是负数,则右移之后在最左边补n个1。 所以负数在进行移位时,最终由于最高位一直补1导致最终结果陷入死循环。故设计出上述代码是由问题的,我们可以对其进行调整。
int hammingWeight(uint32_t n) {
int count = 0;
unsigned int flag = 1;
while(flag)
{
if(n&flag)
count++;
flag = flag << 1;
}
return count;
}
为了避免死循环,此处我们不右移输入的数字n,而是把n和1 按位与 ,判断i的最低位是不是为1,接着把i左移1位,再和n做按位与运算。这样反复右移就能计算出n中二进制位1的个数。这种解法惟一的不足之处是无论n中二进制位有多少个1,都要进行32次循环。那么还能不能在优化一下呢,答案是肯定可以,来看一下最终比较完美的解答:
完美解答:
int hammingWeight(uint32_t n) {
int count = 0;
while(n)
{
++count;
n = (n-1)&n;
}
return count;
}
此处将位运算的灵活性体现到了机制,可以看出代码设计的非常巧妙精简。其精髓就在于此句 n = (n-1)&n
。大家可以自己体会一下此处的妙笔。
标签:min 特点 优化 mingw 移位 测试 精简 strong 比特
原文地址:https://blog.51cto.com/14289099/2546327