剑指Offer——整数中1出现的次数

参考文章:https://www.cnblogs.com/xuanxufeng/p/6854105.html

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。

思路:剑指Offer上用的字符串处理,但是力扣大佬已经可以用5行代码解决。

思路:

我们从一个5位的数字讲起,先考虑其百位为1的情况。分3种情况讨论:

百位数字>=2  example: 31256  当其百位为>=时,有以下这些情况满足(为方便起见,计312为a,56为b):

    100 ~   199

  1100 ~  1199

        .....

 31100 ~ 31199

 余下的都不满足!

因此,百位>=2的5位数字,其百位为1的情况有(a/10+1)*100个数字   (a/10+1)=>对应于 0 ~ 31,且每一个数字,对应范围是100个数(末尾0-99)

百位数字 ==1 example: 31156 当其百位为1时,有以下这些情况满足:

     100 ~   199

   1100 ~  1199

          ......

  30100 ~ 30199

  31100 ~ 31156

因此,百位为1的5位数字,共有(a/10)*100+(b+1)

百位数字 ==0 example: 31056 当其百位为0时,有以下这些情况满足:

     100 ~   199

   1100 ~  1199

 30100 ~ 30199

  其余都不满足

因此,百位数为0的5位数字,共有(a/10)*100个数字满足要求

我们可以进一步统一以下表达方式,即当百位>=2或=0时,有[(a+8)/10]*100,当百位=1时,有[(a+8)/10]*100+(b+1)。用代码表示就是: [(a+8)/10]*100+(a%10==1)?(b+1):0;

为什么要加8呢?因为只有大于2的时候才会产生进位等价于(a/10+1),当等于0和1时就等价于(a/10)。另外,等于1时要单独加上(b+1),这里我们用a对10取余是否等于1的方式判断该百位是否为1。

 

Question:有缺陷或逻辑错误吗?

有人可能会有疑惑,比如11100,这个数在考虑百位为1的时候算作了一次,在考虑千位的时候也算了一次,在考虑万位为1的时候又算了一次,一共计了3次,这不是明显重复吗?

我的回答是,不重复!

分析:题目中要我们统计出现的1的个数,那么我们可以看到11100一共是3个1,如果剔除了重复的情况只考虑一次才会是问题。换言之,在计算从1到n整数中1的出现次数时,我们把10位出现1的情况个数加上百位出现1的情况个数一直加到最高位是1的情况的个数,这里面一个数可能被统计过多次;11100百位出现1,千位和万位都为1,那么被重复统计了3次

 

代码分析:

 

public static int countDigitOne(int n) {
        int ones = 0;
        for (long m = 1; m <= n; m *= 10)
            ones += (n/m + 8) / 10 * m + (n/m % 10 == 1 ? n%m + 1 : 0);
        return ones;
    }

for (long m = 1; m <= n; m *= 10) 在这里的作用是,从个位开始考虑,再到十位,百位,千位,一直到超出这个数!为什么m要用long型呢?因为n可能没有超过整型的表达范围(int刚好可以表示n),而10*m恰恰有可能刚刚超过!ones += (n/m + 8) / 10 * m + (n/m % 10 == 1 ? n%m + 1 : 0); 这里ones用于表示1的个数,当m=100时,n/m其实代表的是a,而n%m代表的是b,此时考虑的是百位为1的情况;当m=1000,自然考虑的就是千位等于1的情况了~ 至于为什么加8,那个三目运算符是干嘛子用的上面都已经讲过了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值