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

剑指 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


暴力操作不可取,直接超时

class Solution:
    def countDigitOne(self, n: int) -> int:
        pre, cur = 0, 0
        def solve(num):#计算当前数值的含1个数
            cnt = 0
            if num == 1: return 1
            elif 1 < num <= 9: return 0
            while num > 9:
                num, b = divmod(num, 10)
                if num == 1: cnt += 1
                if b == 1: cnt += 1
            return cnt

        for i in range(1, n+1):
            cur = pre + solve(i)
            pre = cur
        return cur

《编程之美》上这样说:

  • 设N = abcde ,其中abcde分别为十进制中各位上的数字。
    • 如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。
    • 如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100~199,1100 ~1199,2100 ~2199,,…,11100 ~11199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。注意:高位数字不包括当前位
    • 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100~ 199,1100~ 1199,2100~ 2199,,…,11100~ 11199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共14个,等于低位数字(13)+1。 注意:低位数字不包括当前数字
    • 如果百位上数字大于1(2~ 9),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100~ 199,1100~ 1199,2100 ~ 2199,… 11100~ 11199,12100~12199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。

根据上面的分析进行编程。首先由低位开始计算。

class Solution:
    def countDigitOne(self, n: int) -> int:
        cnt = 0
        layer = 1#从最低位开始算

        while n >= layer:
            high = n // layer // 10         #高位
            cur = n // layer % 10           #当前位
            low = n - n // layer * layer    #低位

            if cur == 0:
                cnt += high * layer
            elif cur == 1:
                cnt += high * layer + low + 1
            else:
                cnt += (high + 1) * layer
            layer *= 10
        
        return cnt
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值