字节笔试题 剑指 Offer 43. 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

解题思路

总体思想就是分类,先求所有数中个位是 1 的个数,再求十位是 1 的个数,再求百位是 1 的个数…
假设 n = xyzdabc,此时我们求千位是 1 的个数,也就是 d 所在的位置。
那么此时有三种情况,
d == 0,那么千位上 1 的个数就是 xyz * 1000
d == 1,那么千位上 1 的个数就是 xyz * 1000 + abc + 1
d > 1,那么千位上 1 的个数就是 xyz * 1000 + 1000
为什么呢?
当我们考虑千位是 1 的时候,我们将千位定为 1,也就是 xyz1abc。
对于 xyz 的话,可以取 0,1,2…(xyz-1),也就是 xyz 种可能。
当 xyz 固定为上边其中的一个数的时候,abc 可以取 0,1,2…999,也就是 1000 种可能。
这样的话,总共就是 xyz*1000 种可能。
注意到,我们前三位只取到了 xyz-1,那么如果取 xyz 呢?
此时就出现了上边的三种情况,取决于 d 的值。
d == 1 的时候,千位刚好是 1,此时 abc 可以取的值就是 0 到 abc ,所以多加了 abc + 1。
d > 1 的时候,d 如果取 1,那么 abc 就可以取 0 到 999,此时就多加了 1000。

class Solution:
    def countDigitOne(self, n: int) -> int:
        # cur表示当前位
        cur = n % 10 
        # high为当前位前面的高位,比如数xyzabc,当前位为a,则高位为xyz,低位为bc
        high = n // 10 
        # low为当前为位后面的低位
        low = 0 
        # digital表示位数,个位为1,十位为10,一次类推
        digital = 1
        # res为总的结果
        res = 0 
        while high!=0 or cur!=0:
            # 如果当前位为0,则只与高位相关
            if cur==0:
                res += high * digital 
            # 如果当前位为1
            elif cur==1:
                res += high * digital + low + 1 
            # 
            else:
                res += high * digital + digital 
            low += cur * digital 
            cur = high % 10
            high //= 10 
            digital *= 10 
        return res 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值