题目:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,一共出现了5次。
int nums[20];
int dp[20][2][20];
//pos表示当前位置,从最高位开始处理
//s表示在之前的pos,数位有无小于最高上限
//ok表示当前状态下1的个数
int dfs(int pos, int s, int ok) {
if (pos < 0)
return ok;
if (dp[pos][s][ok] != -1)
return dp[pos][s][ok];
int up = s ? 9 : nums[pos];
int ans = 0;
for (int i = 0; i <= up; i++)
ans += dfs(pos - 1, s || i < up, ok + (i == 1));
dp[pos][s][ok] = ans;
return ans;
}
int solve(int n) {
memset(dp, -1, sizeof(dp));
int i = 0;
for (; n; i++) {
nums[i] = n % 10;
n /= 10;
}
return dfs(i - 1, 0, 0);
}
int countDigitOne(int n) {
return solve(n);
}
完全可以将题目改变,例如改为:
输入一个整数 n ,求1~n这n个整数的十进制表示中出现1的数字个数
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,一共4个数字出现了1
int nums[20];
int dp[20][2][2];
//pos表示当前位置,从最高位开始处理
//s表示在之前的pos,数位有无小于最高上限
//ok表示当前状态下,是否出现过1
int dfs(int pos, int s, int ok) {
if (pos < 0)
return ok;
if (dp[pos][s][ok] != -1)
return dp[pos][s][ok];
int up = s ? 9 : nums[pos];
int ans = 0;
for (int i = 0; i <= up; i++)
ans += dfs(pos - 1, s || i < up, ok || (i == 1));
dp[pos][s][2] = ans;
return ans;
}
int solve(int n) {
memset(dp, -1, sizeof(dp));
int i = 0;
for (; n; i++) {
nums[i] = n % 10;
n /= 10;
}
return dfs(i - 1, 0, 0);
}
int countDigitOne(int n) {
return solve(n);
}