LeetCode HOT100 - 比特位计数
考虑进阶
O(n) 也就是基本需要从前面已有的结果中得到了
这种形式就是 dp
考虑转移
转移的原则是简单,就是我们怎么从前面已经求好的数,结合当前的信息,得到这个数的结果
一种想法是右移,因为右移后的数一定小于它本身,这样我们只需要根据末尾是 0 还是 1 来判断这个数就可以了 dp[i] = dp[i >> 1] + (i & 1)
另一种是一个常见的结论,也就是 i & (i - 1) 能去掉二进制表示中的最后一个 1,接下来简单看一下原理
设一个数 i 的二进制:
xxxx1000...000
进一步说,如果最低位的那个 1 在某一位上,那么它右边一定全是 0,所以可以写成:
高位部分 1 000...000
而 i - 1 后,最右边那个 1 会变成 0,它右边所有的 0 都会变成 1,也就是:
i = xxxx1000...000
i - 1 = xxxx0111...111
这时候做按位与:
i & (i - 1)
= xxxx0000...000
也就是把最右边的 1 删除了。
这个形式在树状数组中也能遇见
因为 i 和 i & (i - 1) 就相差了一个 1 ,所以代码易得
class Solution {
public:
vector<int> countBits(int n) {
vector<int> dp(n + 1);
dp[0] = 0;
for (int i = 1; i <= n; i++) {
dp[i] = dp[i & (i - 1)] + 1;
}
return dp;
}
};

浙公网安备 33010602011771号