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;
    }
};
posted @ 2026-03-30 19:22  rdcamelot  阅读(26)  评论(0)    收藏  举报