剑指offer43.1~n整数中1出现的次数(找规律)

题目

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:输入:n = 12   输出:5
示例 2:输入:n = 13   输出:6
限制:1 <= n < 2^31

解题思路

 首先可以通过枚举找规律:0~9只有一个1,10~99十位上有10个1,100~999百位上有100个1...以此类推。可以得出结论:

  1. 0~9:只有一个1,那么如果某数是10的a倍,那么个位上就有a个1;
  2. 10~99:十位上有10个1,即10~19,那么如果某数是100的a倍,是10的b倍,那么十位有a*10个1,个位有b个1,共(a*10+b)个1;
  3. 100~999:百位上有100个,即100~199,那么如果某数是1000的a倍,100的b倍,是10的c倍,那么百位有a*100个1,十位有b*10个1,个位有c个1,共(a*100,b*10+c)个1;
  4. ...

余数规则:

如果某数是100的x倍,根据余数y判断实际十位共有几个1:

  • y>=20: (x+1)*10
  • 10<=y<20: y+1+(x-1)*10
  • y<10: x*10

比如:n=2012,那么1~2012共有几个1,

  1. a = 1, b = 10, 根据x, y = divmod(n, b)可知,x = 201, y = 2, 因为2 >= 2 * a,那么个位共有 201 + 1个1, one_count = 202
  2. a = 10, b = 100, 此时x = 20, y = 12, 因为 a <= 12 < 2 * a,那么十位共有 (12 + 1 + (20 -1) * 10)个1, one_count = 202 + 203 = 405
  3. a = 100, b = 1000, 此时x = 2, y = 12, 因为 12 < a,那么百位共有 (2 * 100)个1, one_count = 405 + 200 = 605
  4. a = 1000, b = 100000, 此时x = 0, y = 2012, 因为 2012 >= 2 * a,那么千位共有1000个1, one_count = 605 + 1000 = 1605

代码

class Solution:
    def countDigitOne(self, n: int) -> int:
        a, b, one_count = 1, 10, 0
        while n >= a:
            x, y = divmod(n, b)
            
            if y >= a * 2:
                one_count += (x + 1) * a
            elif y >= a:
                one_count += y + 1 + (x - 1) * a
            else:
                one_count += x * a 

            a, b = b, b*10 
        
        return one_count

参考链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/solution/ji-jian-jie-fa-by-harrisliao/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值