题目来源:https://leetcode-cn.com/problems/number-of-digit-one/
大致题意:
给定一个数字n,求出所有 大于0 且 小于等于n 的数中,数字1出现的次数
思路
可以先求出某一位上,1可能出现的次数,然后推广到所有位。
比如,求 1234 在 十位 上 数字1 出现的次数。
- 首先,0 - 1200 之间 从十位到百位,有 1200 / 100 = 12次进位,而对于每次进位之间,都会有100个数,期间会有 10~19 出现,也就是十位上数字1出现10次。
- 因而,0-1200 之间 十位上数字出现次数为 (1200 / 100 )* 10
- 而 0-34 之间,十位上数字1出现的次数,要根据十位上的数字来判断。若其小于1,那么显然次数为 0;若其等于1,那么次数为 个位上的数字+1;若其大于1,那么次数为 10。
- 因而,0-34之间十位上数字1出现次数为
min(max(34 - 10 + 1, 0), 0)
- 推广到所有位,假设当前位为10^k,则有
- (num / 10^(k+1)) * 10^k + min(max(num%10^(k+1) - 10^k + 1, 0), 10^k)
代码:
public int countDigitOne(int n) {
// sum += [num / 10^(k+1)] * 10^k + min(max(num%10^(k+1)-10^k+1, 0), 10^k)
int ans = 0;
long base = 1; // 表示 10^k
for(int k = 0; n >= base; k++) {
ans += (n / (base * 10)) * base + Math.min(Math.max(n%(base*10) - base + 1, 0), base);
base *= 10;
}
return ans;
}