一、题目
1、题目描述
给定一个正整数
n
,请你统计在[0, n]
范围的非负整数中,有多少个整数的二进制表示中不存在 连续的 1。示例 1:
输入: n = 5 输出: 5 解释: 下面列出范围在 [0, 5] 的非负整数与其对应的二进制表示: 0 : 0 1 : 1 2 : 10 3 : 11 4 : 100 5 : 101 其中,只有整数 3 违反规则(有两个连续的 1 ),其他 5 个满足规则。
2、接口描述
cpp
class Solution {
public:
int findIntegers(int n) {
}
};
3、原题链接
二、解题报告
1、思路分析
本题是数位DP的模板题,关于数位DP笔者将于明日发布详细讲解,这里仅给出本题解法
我们设计状态f[i][j]为剩余i位未处理,上一位为j情况下目标数字的数目,这也是数位dp问题通用状态设计
那么我们只需要枚举下一位即可,如果前面的位严格小于给定数字的对应位,那么可以从0枚举到9,否则只能枚举到给定数字对应位
对于连续1的情况不进行枚举即可
2、复杂度
时间复杂度: O(log n) 空间复杂度:O(log n)
3、代码详解
cpp
int f[32][32] , d[32] , cnt = 0;
class Solution {
public:
Solution()
{memset(f , -1 , sizeof(f));}
int dfs(int n , int pre , bool lim)
{
if(!n) return 1;
if(lim && ~f[n][pre]) return f[n][pre];
int ceil = lim ? 1 : d[n];
int res = 0;
for(int i = 0 ; i <= ceil ; i++)
if(pre == 1 && i == 1) continue;
else res += dfs(n - 1 , i , lim || i < ceil);
if(lim)
f[n][pre] = res;
return res;
}
int getnum(int x)
{
cnt = 0;
while(x) d[++cnt] = x % 2 , x /= 2;
return dfs(cnt , 0 , false);
}
int findIntegers(int n) {
return getnum(n);
}
};