数字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开始
}
};