剑指offer 43 1~n整数中1出现的次数

题意是给定n,输出1~n个数中,位数上有1的在每个数出现的次数和;比如n=12,则位数上有1的有1,10,11,12,一共4个,但统计的是1出现的次数,则是5次,11出现了2次1;
思路是:统计一个数,其某位上出现1的总次数,然后将该数每一位上的总次数加起来就是最后的总次数
规律题,当该位是0时,则出现的总次数是highdigst;当该位是>0时,则出现的总次数是highdigst+low+1; 当该位是<0时,则出现的总次数是(high+1)*digst
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
while high != 0 or cur != 0: # 当 high 和 cur 同时为 0 时,说明已经越过最高位,因此跳出
从个位到高位的统计,按2314这个例子思考

class Solution(object):
    def countDigitOne(self, n):
        """
        :type n: int
        :rtype: int
        """
        digst , res =1,0
        high , cur , low = n//10,n%10,0
        while high!=0 or cur !=0:  #本题的难点在于循环终止条件的确定;high和cur同时为0时,说明已经越过高位,因此跳出
            if cur <1:
                res +=high*digst
            elif cur==1:
                res +=high*digst + low +1
            else:
                res +=(high+1)*digst
            low += cur*digst
            cur = high%10
            high //=10
            digst *=10
        return res

时间复杂度 O(logn) : 循环内的计算操作使用 O(1)时间;循环次数为数字 n的位数,即 log10n ,因此循环使用 O(logn) 时间
空间复杂度 O(1) : 几个变量使用常数大小的额外空间
本题另一个收获是时间复杂度的计算,因为是位数的变化,所以是以10为底的log复杂度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值