整数中1出现的次数

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?
1~13中包含1的数字有1、10、11、12、13因此共出现6次。

众所周知,对于一个整数而言,它是由个位、十位、百位、… 组成的。在这里我们用m代表1、10、 100、1000等等,用于之后各个位的表示。

下面来看一下具体的一个整数的例子。比如这个整数是2561482,即求从1到2561482中,1出现的次数。

我们先把整数2561482按照百位m = 100划分为两部分,a=25614和b=82,也就是有2561482 = a*100+b。

那么,当我们的这个整数在百位上取“1”的时候,a这个部分总共有多少个数呢?不难看出, 一共有2562(=2561+1)个数,也就是说,当百位数为1的时候,百位数前面的数一共有0-2562可以选择,这时,百位数之后的数就可以任意取了,从0-99都可以,一共有100种取法。对于在百位上的分割, 用数学公式表示就是:百位数字不为1,对其取1一共有 (a//10 + 1) * 100 个数。这里的 // 是Python中的整除符号。比如 20 // 3 == 6。

百位分割完成了,我们再来看一下千位的分割。m = 1000时,a = 2561, b = 482。同样,我们先看千位数之前的数,本应该有 257 (=256+1) 种选择,但和上面的例子不一样的是,在上面的例子中,百位数子是4 > 1,所以对于百位数字为1,可以取到 100 - 199 一共100个数字。而在千位上,千位数字已经1了,所以后面的数字只能取到 1000-1482 ,一共483种情况,将a和b的情况组合,共有257 * 1000 + 483种情况,应用到一般情况,即千位数字为1,一共有 (a // 10 *1000) + ( b + 1)。

而如果某位位数字为0 < 1,则需要舍弃这一位的情况。

因此,对于整个过程进行归纳整理可知,需要将每一位分为 0、1 以及 >=2 这三种情况,对于每一个m<=n:

if (n//m) % 10 != 0 and (n//m) % 10 != 1:
    count += (n // m // 10 + 1) * m
elif (n//m) % 10 == 1:
    count += (n // m // 10) * m + n % m + 1

其中,(n//m)%10是用来判断当前位的数值,如果当前位数值>=2,则执行count += (n // 10 // m + 1) * m,如果当前位数值为1,则执行count += (n // m // 10) * m + n % m + 1

以上的代码虽然可以得到正确答案,但是还是很繁琐。所以可以依据数学推导对函数进行进一步简化。我们可以想一下上面的对应的分组的三种情况:0、1 以及 >=2。当当前位数值大于等于2的时候,比当前位数值等于1的情况,我们多乘了一个m,考虑到x>=2, x+8>=10,因此可以吧这个多乘的一个m利用加8进位来替代。同时,我们应该注意到,只有对于当前位为1的情况而言,才会发生 n%m+1的情况,因此上面的那段代码可以修改为:

ones += (n // m + 8) // 10 * m + (n // m % 10 == 1) * (n % m + 1)

这样看起来就简洁多了。最后放下完整的代码:

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        ones, m = 0, 1
        while m <= n:
            ones += (n // m + 8) // 10 * m + (n // m % 10 == 1) * (n % m + 1)
            m *= 10
        return ones

s = Solution()
print(s.NumberOf1Between1AndN_Solution(352413))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值