LeetCode--剑指 Offer 43. 1~n 整数中 1 出现的次数

剑指 Offer 43. 1~n 整数中 1 出现的次数

思路:枚举每一数位上 1 的个数
在这里插入图片描述
公式:
在这里插入图片描述
比如:计算321
统计10位上出现的1的次数
1.对于从0开始的每100个数,十位上的1都会出现10次,321拥有3个这样的循环,每个循环 十位 上都出现了10次1,一共出现了30次1,这部分为⌊ 321/100 ⌋×10
2.对于不完整的循环,存在三种情况,

  1. 305:十位为0,不会出现1,
  2. 315:十位为1,不完全出现1,会出现15 - 10 + 1个1
  3. 325:则会出现全部的1
    计算时可以用取余数的方式拿到除去高位剩下的数,与10比较,计算与10的差值,由于是从10开始计算,需要+1,最后根据结果的正负,如果是负数,代表没有1,取0,如果是正数,可能会存在超过10的情况,所以我们取最多不超过10.
    min(max(n −100+1,0),100)

4.最后将两部分加起来即可

/*
剑指 Offer 43. 1~n 整数中 1 出现的次数
 */

public class SolutionJZ43 {
  public int countDigitOne(int n) {
    // 从第一位开始计算
    long mulk = 1;
    // 总数为0
    int ans = 0;
    while (n >= mulk) {
      // 拿到当前数位个数
      long a = (n / (mulk * 10));
      // 计算当前数位正多少 比如 87655 选择千位,就是87
      long b = a * mulk;
      // 计算当前位置下的余数 比如 87655 选择千位,就是655
      long c = n % (mulk * 10);
      // 当 n < mulk  时,「mulk位」上不会出现 1
      // 当 mulk < n < mulk * 2 时,「mulk位」上出现 1 的范围为 [mulk, n] 所以出现了 n - 100 + 1次1
      // 当  ≥ mulk * 2 时,「mulk位」上出现了全部 1。
      long d = Math.max(c - mulk + 1, 0);
      // n < 100 答案取0 ,n >= 100 , 答案选当前位数
      long e = Math.min(d, mulk);
      ans +=  b + e;
      mulk *= 10;
    }
    return ans;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值