力扣 233. 数字 1 的个数

题目来源: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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值