LeetCode 热题 HOT 100 第六十五天 338. 比特位计数 简单题 用python3求解

题目地址
给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:
输入:n = 2
输出:[0,1,1]
解释:
0 --> 0
1 --> 1
2 --> 10

示例 2:
输入:n = 5
输出:[0,1,1,2,1,2]
解释:
0 --> 0
1 --> 1
2 --> 10
3 --> 11
4 --> 100
5 --> 101

提示:
0 <= n <= 10^5

进阶:
很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?
你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount )
LeetCode 热题 HOT 100 第六十五天 338. 比特位计数 简单题 用python3求解_第1张图片
LeetCode 热题 HOT 100 第六十五天 338. 比特位计数 简单题 用python3求解_第2张图片
解法:动态规划+位运算
对于正整数x,将其二进制表示右移一位,等价于将其二进制表示的最低位去掉,得到的数是⌊x/2⌋(即x除以2的商向下取整)。如果bits[⌊x/2⌋]的值已知,则可以得到bits[x]的值:

  • 如果x是偶数,则bits[x]=bits[⌊x/2⌋];
  • 如果 xx 是奇数,则bits[x]=bits[⌊x/2⌋]+1。

上述两种情况可以合并成:bits[x]的值等于bits[⌊x/2⌋]的值加上x除以2的余数。

由于⌊x/2⌋可以通过x>>1得到,x除以2的余数可以通过x&1得到,因此有:bits[x]=bits[x>>1]+(x&1)。

遍历从1到n的每个正整数i,计算bits的值。最终得到的数组bits即为答案。
LeetCode 热题 HOT 100 第六十五天 338. 比特位计数 简单题 用python3求解_第3张图片
位运算的基础知识:
n&1:
&运算通常用于二进制取位操作,例如一个数&1的结果就是取二进制的最末位。这可以用来判断一个整数的奇偶,二进制的最末位为0表示该数为偶数,最末位为1表示该数为奇数。
也就是说,n&1 就是——判断n是否为奇数
因为n为奇数时,对应的二进制数最低位一定为1,n&1的结果就是1
n为偶数时,相应的最低位为0,n&1的结果就是0,
这里也可以写 n&1 ==1 或者写 n%2 == 1 或者写 n%2

>>1:
>>1 等价于 /2
<<1 等价于 *2

以n=5为例,跟着代码走一遍:
LeetCode 热题 HOT 100 第六十五天 338. 比特位计数 简单题 用python3求解_第4张图片
代码实现:

class Solution:
    def countBits(self, n: int) -> List[int]:
        bits = [0]
        for i in range(1, n + 1):
            bits.append(bits[i >> 1] + (i & 1))
        return bits

你可能感兴趣的:(LeetCode,热题,HOT,leetcode,动态规划,算法,数据结构,力扣)