题目
动态规划
public class Main {
public static void main(String[] args) {
Main main = new Main();
main.countBits(1);
}
public int[] countBits(int num) {
if (num == 0) {
return new int[]{0};
}
// 观察发现每个元素二进制1的个数会由之前的某个元素,通过首位添加1一个1得到
// 具体由哪个元素和当前元素的大小, 以及和最接近当前元素的2^m次的值有关
// 首先0, 1 两个数字是起始数字 dp[0] = 0; dp[1] = 1;
// 例如2 >= 2^1 那么dp[2] = dp[2 - 2^1] + 1= dp[0] + 1
// 2^2 > 3 >= 2^1 dp[3] = dp[3 - 2^1] + 1 = dp[1] + 1
// 例如8 >= 2^3 那dp[8] = dp[8 - 2^3] + 1 = dp[0] + 1
// 以此类推需要判断最接近当前元素的2^m次的值
// 生成一个最大值小于num的 2^m的数组
int [] support = new int[32];
for (int i = 0;i < num; i ++) {
int value = calculate(i + 1);
support[i] = value;
if (value > num) {
break;
}
}
int [] dp = new int[num + 1];
dp[0] = 0;
dp[1] = 1;
int index = 0;
int pre = support[index];
int after = support[index + 1];
for (int i = 2; i <= num; i ++) {
if (i >= pre && i < after) {
dp[i] = dp[i - pre] + 1;
} else {
dp[i] = dp[i - after] + 1;
index = index + 1;
pre = support[index];
after = support[index + 1];
}
}
return dp;
}
private int calculate(int n) {
if (n == 0)
return 1;
return 2 * calculate(n - 1);
}
}
基本思路
-
-
注意2^m次的求发, 注意求出多少2^m次的值就够用了, 不用多求
-
每次使用注意替换两个support的值就可以了