数字1的个数

给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。

一. 数位dp

class Solution {
public:
    int countDigitOne(int n) {
        auto s = to_string(n); //转字符串逐位递归分析
        int m = s.length(), memo[m][m];
        memset(memo,-1,sizeof(memo));
        function<int(int, int, bool)> f = [&](int i,int cnt, bool is_limit) -> int {
            if (i == m) return cnt;//边界直接返回前面累积的1
            if (!is_limit&&memo[i][cnt]!= -1) //已经存储过,直接剪枝返回
                return memo[i][cnt];
            int res = 0; //计算1出现的个数
            int up = is_limit ? s[i] - '0' : 9; // 根据受限与否决定枚举数上界
            //做选择
            for (int d = 0; d <= up; ++d) 
                    res += f(i + 1, cnt + (d == 1), is_limit && d == up);//移动到下一位,判断限制情况

            if (!is_limit) //记录非限制数
                memo[i][cnt] = res;
            return res;
        };
        return f(0,0,true);   //从下标0开始
    }
};
posted @ 2023-06-07 04:04  失控D大白兔  阅读(15)  评论(0编辑  收藏  举报