我们定义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合并,因为我们只需要上一位的数字和当前位的数字,不需要花一个数组去存储所有位数。但这样会使得我们花费更多的时间因为我们还是需要去获取数组的长度。