题目
给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数。
示例1:
输入:n = 13
输出:6
示例2:
输入:n = 0
输出:0
提示:
0 <= n <= 2 * 109
思路
动态规划
我首先想到的是枚举,但是毫无疑问超时了,数位dp看的是题解写的。
枚举
思路:dp[i]表示1~i里已经出现的1的总数,状态方程:dp[i] = dp[i - 1] + 这个数中出现的1的次数
class Solution {
public:
int cacul_1(int num) {
int ans = 0;
while(num) {
ans += num % 10 == 1 ? 1 : 0;
}
return ans;
}
int countDigitOne(int n) {
vector<int>dp(n + 1,0);
for(int i = 1; i <= n; i++) {
dp[i] = dp[i - 1] + cacul_1(i);
}
return dp[n];
}
};
数位dp
这个思路是考虑每一个数位的情况,分别有0,1,其它三种情况。假设有220,则个位出现1的数有:1,11,21....211一共22个;如果是221,则有1,11,21....211 + 221共23个;如果是223则也是23个。。。解释起来好麻烦,建议看k神的讲解
class Solution {
public:
int countDigitOne(int n) {
long long base = 1;
int high = n,low = 0,cur = 0,ans = 0;
while(high != 0 || cur != 0) {
cur = high % 10;
high /= 10;
if(cur == 0) {
ans += high * base;
}else if(cur == 1){
ans += high * base + low + 1;
}else {
ans += (high + 1) * base;
}
low = cur * base + low;
base *= 10;
}
return ans;
}
};
本文探讨了一种动态规划方法来解决计算小于等于给定整数n的所有非负整数中数字1出现次数的问题。首先介绍了基本的枚举思路,但因为时间复杂度过高导致超时。接着,详细阐述了动态规划的数位DP解决方案,通过考虑每个数位上的不同情况(0, 1, 其他),逐步计算出1的总数。最后,给出了两种不同的数位DP实现,帮助理解这个问题的高效解法。

453

被折叠的 条评论
为什么被折叠?



