题目
思路
这道题并不难但是依然出了一点点问题…(是的一点点而已)
我一开始尝试使用map把这个东西直接给转化成一堆01的list,但是出现了bug。我刚开始以为是因为python3的map返回的是一个迭代器,但是在外面加了list之后倒是不报bug了,结果反而不对了。于是我猜问题可能是在二进制上,于是用bin函数尝试转换为二进制,最后的答案如下:
1 | class Solution(object): |
还有一种暴力解法,遍历n并且记录1的个数:
1 | def hammingWeight(n: int) -> int: |
然后有一个位运算的解法,很trick,如果我自己想我肯定想不出来,代码如下:
1 | def hammingWeight(n: int) -> int: |
位运算的相关介绍在这里:位运算有什么奇技淫巧? - 力扣(LeetCode)的回答。
也就是说,有一个方法,可以把最右边的 1 置为 0,举个具体的例子:
比如十进制的 10,二进制形式是 1010,然后我们只需要把它和 9 进行按位与操作,也就是 10 & 9 = (1010) & (1001) = 1000,也就是把 1010 最右边的 1 置为 0。
规律就是对于任意一个数 n,然后 n & (n-1) 的结果就是把 n 的最右边的 1 置为 0 。
也比较好理解,当我们对一个数减 1 的话,比如原来的数是 …1010000,然后减一就会向前借位,直到遇到最右边的第一个 1,变成 …1001111,然后我们把它和原数按位与,就会把从原数最右边 1 开始的位置全部置零了 …10000000。
有了这个技巧,我们只需要把原数依次将最右边的 1 置为 0,直到原数变成 0,记录总共操作了几次即可。
除了以上方法之外好像还有一种比特位的方法,朋友给我说了解法但是不好放在这里,只能等我看明白之后尝试重写再放出了。
另:这道题同时也是CSAPP的一道lab题。