【Leetcode】Numbers of 1 bits

来源:互联网 发布:sql注入的危害 编辑:程序博客网 时间:2024/06/01 09:16

本文参考了:

http://blog.csdn.net/canglingye/article/details/44177479


我刚一看,这不挺简单的吗?不断移位,看最低位是不是1,是1就记录一下,很简单嘛,而且移位又那么快。

class Solution:    def hammingWeight(self, n):        hw = 0        while n != 0:            if n & 1:                hw += 1            n >>= 1        return hw

然后提交就过了。上网一看。自己写的代码简直像是用脚写的……还if个毛啊。直接hw += (n & 1)就得了。

但这都不是重点。我又用JavaScript写了一次。跪了。(切不可乱装逼,但装逼的好处就是挫败以后能长知识)

var hammingWeight = function(n) {    var hw = 0;    while(n != 0){        if (n & 1) {            hw ++;        }        n >>= 1;    }    return hw;};

错误:

Input:2147483648 (10000000000000000000000000000000)Output:0Expected:1

Python因为不太在意变量类型,反正一大了就变长整型,所以没什么问题。C++、Java等应该也没问题,只要你指定参数是unsigned int。问题就出现在这个表面上不区分类型(一律都是var)实际会出问题的js。参考以下文章:

http://www.jb51.net/article/44242.htm

在 JavaScript 中,所有整数字变量默认都是有符号整数。JavaScript 进行位操作时,也是采用32位有符号整型,这意味着其转换的结果也是32位有符号整型。

有些时候,我们进行移位会出现意想不到的结果,以下是C语言 与 JS 的对比。

C语言
unsigned int a = 3774191835u;
unsigned int b = a >> 2;
/* b == 943547958 */

-------------------------------

JavaScript
var a = 3774191835;
var b = a >> 2;
/* b == -130193866 */


所以像我刚才那样的写法,移位最后会陷入死循环:10000000000000000000000000000000→11000000000000000000000000000000→11100000000000000000000000000000→……→11111111111111111111111111111111,到最后-1右移一位还是-1,死循环。

(如果把n!=0换成n>0也不行,负数直接退出循环。下文还会说。)

解决方案呢:参考
http://blog.163.com/cjd_cd/blog/static/461155652012630665455/
无符号移位符:>>>
例如:(以下在Nodejs中运行)
>-1 >>> 1  
2147483647 (2 ^ 32 - 1)
>a = -1 >>> 0
4294967295 (相当于由int转成unsigned int了)
>a << 0
-1 (相当于由unsigned int 转成int了)

到此为止,我们似乎已经解决了问题。但其实,还有一种更有效率的算法,它同时也能巧妙规避上述的移位错误。
var hammingWeight = function(n) {    var hw = 0;    while(n){        n &= (n - 1);        hw ++;    }    return hw;};
每进行一次n &= (n-1),就把原n的最后一个1去掉,这样循环进行了几次,就说明有多少位的1。这里要注意,while循环条件(相当于n!=0)不能替换成n > 0,原因和刚才说的一样,大于2147483647的数在进行过位运算以后会被理解为负数,这样就不满足循环条件。
比如:Input:4294967295 (11111111111111111111111111111111)Output:1Expected:32
进入了循环,位运算后,n被赋值:11111111111111111111111111111110,我们期望的是4294967294,但实际解读为-2,hw++,退出循环。

0 0
原创粉丝点击