leetcode:233. 数字 1 的个数
题目描述:
给定一个整数 n
,计算所有小于等于 n
的非负整数中数字 1
出现的个数。
示例 1:
输入:n = 13
输出:6
示例 2:
输入:n = 0
输出:0
0 <= n <= 10^9
解答:
由于n最大为10^9,最大是一个10位的整数,所以我们枚举每个位上1出现的次数就行了。
用百位来举例:当n=1234567时,我们统计百位上1出现的次数,从0到999,百位上的1
,只有100到199,出现了100次,并且从1000开始,千位上的数每增加1,0到999就会再次循环一次(意思就是1000到1999,2000到2999千位增加了1,0到999出现了一次),所以1234567百位上的1,就是1234*100个
到这里我们就只计算了1234000中1的个数,后面的567(这里记作m)没有算进去。这里就要分类讨论:
- m < 100 时,百位没有1,所以百位上1的个数为0
- 100 <= m < 200时,百位为1的个数就是 m - 100 + 1;(比如123时,100~123这些数在百位上1有24个)
- m > 200时,那么百位上的数一定是100 (大于200后百位上就没有1了)
可以发现,m < 0 时,m - 100 + 1 <= 0, 我们要得到0,m > 200 时,m - 100 + 1 > 100我们要得到100,所以剩下的这部分,百位上为1的个数为: min(max(m - 100 + 1, 0), 100)
以上两部分加起来,就是百位上1的总数:(n / 1000)*100 + min(max(m - 100 + 1, 0), 100)
同理,其他位上1的个数也可以得出来: (n / 10(k+1))*10k + min(max(m - 10^k + 1, 0), 10^k),其中k从0开始。
注意:(n/10(k+1))*10k不要化简为 (n/10),因为(1234567%1000)*100=123400 而1234567/10=123456
class Solution {
public int countDigitOne(int n) {
int count = 0;
for(long i = 1; i <= n; i *= 10) {
long divider = i * 10;
count += (n / divider) * i + Math.min(Math.max(n % divider - i + 1, 0), i);
}
return count;
}
}