leetcode233. 数字 1 的个数

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出现的次数,从0999,`百位上的1`,只有100199,出现了100次,并且从1000开始,千位上的数每增加1,0999就会再次循环一次(意思就是10001999,20002999千位增加了1,0999出现了一次),所以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;
    }
}

你可能感兴趣的:(leetcode题目,java)