我们先计算 0-9, 0-99 ,0-999的答案
cnt[0-9]=1
cnt[00-99]=十位上的1 + 个位上的1 = 10 + 10组 * cnt[0-9]
cnt[000-999]=百位上的1 + 十位上的1 + 个位上的1 = 100 + 10组 * cnt[00-99]
找到规律:cnt[0-n位9] =10(n-1) + 10 * cnt[0-(n-1)位9]
然后我们从最低位开始计算答案,这里以195为例子
1.计算1位,0~5,只有1个1
2.计算2位,00~95,00~95 = 90 ~95 + 00 ~ 89
- 00~89:
个位的1:有0~8共9组cnt[0~9],也就是9 * cnt[1]
十位的1:10~19,共十个 - 90~95:也就是0~5,也就是之前步骤1计算过的
3.计算3位,195 = 100 ~ 195 + 00~99
- 00~99:cnt[2]
- 100~195:
百位的1:95+1 个(别忘了100),可以用substring加上parseInt然后加上个1直接获得
00~95 : 之前步骤2计算过的
class Solution {
public int countDigitOne(int n) {
String s = String.valueOf(n);
int len = s.length();
// cnt[n]:n位数[0-n个9]的答案
int[] cnt = new int[len+1];
int temp = 10;
cnt[1] = 1;
for (int i = 2; i <= len; i++) {
cnt[i] = temp + 10 * cnt[i-1];
temp *= 10;
}
int dp = s.charAt(len-1) == '0' ? 0:1;
// 逆序遍历
temp = 1;
for (int i = len - 2; i >= 0; i--) {
temp *= 10;
// 现在的实际长度
int nowCnt = len - i;
if(s.charAt(i) == '0') {
}else if(s.charAt(i) == '1') {
int after = Integer.parseInt(s.substring(i+1, len));
// 最高位的1
dp += (1 + after) + cnt[nowCnt - 1];
}else {
int full = (int) (s.charAt(i) - '0');
dp += temp + full * cnt[nowCnt - 1];
}
}
return dp;
}
}