我们定义dp[i][j]为第i位为j的合法总数,通过static预处理所有结果。
针对某一个数,我们先将其转化为二进制,然后从最高位开始往下找;
如果当前位为1,则代表若当前为取0,其余低位可以随意取,即ans += dp[i][0],这一位就固定为1了,当前一位也是1的时候,我们就可以返回结果了;
如果当前位为0,则直接跳过当前位。
如果成功遍历到最低位,还要加上最大的那个结果(也就是一开始给的参数n),ans+=1;
class Solution {
// 第i位为j的合法总数
static int[][] dp = new int[30][2];
static {
dp[0][0] = 1;
dp[0][1] = 1;
for (int i = 1; i <= 29; i++) {
dp[i][0] = dp[i - 1][0] + dp[i - 1][1];
dp[i][1] = dp[i - 1][0];
}
}
boolean[] getArray(int n) {
int st = 0;
boolean[] integers = new boolean[31];
do {
integers[st++] = n % 2 == 1;
n >>= 1;
} while (n != 0);
// 辅助位
integers[st] = false;
return integers;
}
public int findIntegers(int n) {
int ans = 0;
boolean[] array = getArray(n);
// 去除掉辅助位
int len = array.length - 1;
for (int i = len - 1; i >= 0; i--) {
if (array[i]) {
ans += dp[i][0];
if (array[i + 1]) {
return ans;
}
}
}
return ans + 1;
}
}
可以优化的地方就是将getArray和findIntegers合并,因为我们只需要上一位的数字和当前位的数字,不需要花一个数组去存储所有位数。但这样会使得我们花费更多的时间因为我们还是需要去获取数组的长度。

这篇博客探讨了一种优化算法,用于计算给定整数的二进制表示中,不包含连续1的非负整数子集的数量。通过预处理动态规划数组dp,博主展示了如何从高位到低位遍历二进制数,动态更新合法组合计数。在遍历过程中,分别处理当前位为1和0的情况,并在遍历结束后加上最大结果。文章指出,虽然可以进一步合并getArray和findIntegers方法,但这可能导致遍历时间增加。
368

被折叠的 条评论
为什么被折叠?



