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出现的次数,从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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值