不含连续1的非负整数

给定一个正整数 n ,请你统计在 [0, n] 范围的非负整数中,有多少个整数的二进制表示中不存在连续的 1 。

1. 数位dp

class Solution {
public:
    int findIntegers(int n) {
        int m=  __lg(n); //转字符串逐位递归分析
        int memo[m+1][2];
        memset(memo,-1,sizeof(memo));
        function<int(int, bool, bool)> f = [&](int i,bool pre, bool is_limit) -> int {
            if (i < 0) return 1;//边界直接返回
            if (!is_limit&&memo[i][pre]!= -1) //已经存储过,直接剪枝返回
                return memo[i][pre];
            int res = 0; //计算
            int up = is_limit ? n>>i&1 : 1; // 受限取对应位值
            //做选择
            res += f(i - 1, 0, is_limit && 0 == up);//取0
            if(up==1&&pre==0) res+= f(i - 1, 1, is_limit && 1 == up);//取1
            if (!is_limit) //记录非限制数
                memo[i][pre] = res;
            return res;
        };
        return f(m,0,true);   //从下标m开始,方便位运算
    }
};

2. 套用模板

class Solution {
public:
    int findIntegers(int n) {
        string s = bitset<32>(n).to_string();//这里直接转化为字符串
        int m = s.size();
        int dp[m][2];
        memset(dp, -1, sizeof(dp));
        function<int(int, bool, bool)>f = [&](int i, bool is_pre1, bool is_limit)->int {
            if(i==m) return 1;
            if(!is_limit && dp[i][is_pre1] > 0) return dp[i][is_pre1]; 
            int res = 0;
            for(int d=0, up = is_limit ? s[i]-'0': 1; d <= up; ++d){
                if( d== 1 && is_pre1) continue;
                res += f(i+1, d == 1, is_limit && d==up);
            }
            if(!is_limit) dp[i][is_pre1] = res;
            return res;
        };
        return f(0, false, true);//从下标0开始
    }
};
posted @ 2023-06-07 04:50  失控D大白兔  阅读(7)  评论(0编辑  收藏  举报