Dynamic Programming学习笔记 (23) - 比特位计数 (力扣# 338)

133 阅读1分钟

本题出自力扣题库第338题。

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

示例:

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

题解:

对于大多数DP应用而言,解题的第一步都是从给定的题面和实例中找出问题内在的数学和逻辑的关系。对于此题而言,我们首先列出从0开始的若干个整数的二级制形式。

0: 0000
1: 0001
2: 0010
3: 0011
4: 0100
5: 0101     
6: 0110     

从中我们可以看到当整数n是·奇数时,其二级制形式中1的数量就比n-1的多一个,因为 n = (n - 1) + 1, 而且n - 1是偶数,所以最低位是0,加1之后不会产生进位的情况;

3 (0011) = 2 (0010) + 1
5 (0101) = 4 (0100) + 1

而当n是偶数时,其二级制形式中1的数量则和n/2的相同,因为当一个整数乘以2时,对于二级制表达而言是整体左移一位,所以1的数量并没有改变。

4 (0100) = 2 (0010) * 2
6 (0110) = 3 (0011) * 2

从以上观察出发,我们可以定义如下的DP表达式:

F(n) 
= 0, n =0
= F(n/2), n是偶数
= F(n - 1) + 1, n是奇数

Java实现:

class Solution {
    public int[] countBits(int n) {
        int[] dp = new int[n + 1];

        for (int i = 1; i <=n; i ++) {
            if (i % 2 == 0) {
                dp[i] = dp[i / 2];
            } else {
                dp[i] = dp[i - 1] + 1;
            }
        }
        return dp;
    }
}