题意是给定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复杂度