3.统计数字(Digit Count)
计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值。
首先是,惯用思维,2个循环解决,这样做的时间复杂度为O(n*2)
1 class Solution: 2 """ 3 @param k: An integer 4 @param n: An integer 5 @return: An integer denote the count of digit k in 1..n 6 """ 7 def digitCounts(self, k, n): 8 # write your code here 9 times = 0 10 11 for i in range(n+1): 12 item = str(i) 13 while len(item) > 0: 14 if item[0:1] == str(k): 15 times += 1 16 item = item[1:] 17 return times
提交成功后,看到讨论区有时间复杂度为O(log(n))的解法,搞懂思路后,终于自己实现了
本题求k出现的次数,其实可以等价于求k在各个数位上出现的次数之和
以n=3154为例,分情况讨论
设k所在数位为index(比如k在千位,index就是3;k在百位,index就是2)
设digit为k所在数位上,n对应的数值(比如k在千位,digit就是3;k在百位,digit就是1)
设k所在数位前的数为高位high,k所在数位后的数为低位low(比如k在百位,high就是3,low就是54;k在十位,high就是31,low就是4)
一、当k>digit时
1.k在个位:(000~314)k high=315 index=0
共有315*1 = high*(10^index) = 315种可能
2.k在十位:(00~30)k(0~9) high=31 index=1
共31*10 = high*(10^index) = 310种可能
3.k在百位:(0~2)k(00~99) high=3 index=2
共3*100 = high*(10^index) = 300种可能
4.k在千位 high=0 index=3
共有0*1000 = high*(10^index) = 0种可能
所以,当k>digit时,k出现次数为high*(10^index)
二、当k=digit时
1.k在个位:(000~315)k high=315 low=0 index=0
共有316 = 315*10^0+0+1 = high*(10^index)+low+1 = 316种可能
2.k在十位:(00~30)k(0~9)+31k(0~4) high=31 low=4 index=1
共31*10+5 = 31*10^1+4+1 = high*(10^index)+low+1 = 315种可能
3.k在百位:(0~2)k(00~99)+3k(00~54) high=3 low=54 index=2
共3*100+55 = 3*10^2+54+1 = high*(10^index)+low+1 = 355种可能
4.k在千位:k(000~154) high=0 low=154 index=3
共0*1000+155 = 0*10^3+154+1 = high*(10^index)+low+1 = 155种可能
所以,当k>digit时,k出现次数为high*(10^index)+low+1
三、当k<digit时
1.k在个位:(000~315)k high=315 index=0
共有316*1 = (315+1)*(10^0) = (hith+1)*(10^index) = 316种可能
2.k在十位:(00~31)k(0~9) high=31 index=1
共32*10+10 = (31+1)*(10^1) = (hith+1)*(10^index) = 320种可能
3.k在百位:(0~3)k(00~99) high=3 index=2
共4*(10^2) = (3+1)*(10^2) = (hith+1)*(10^index) = 400种可能
4.k在千位:k(000~999) high=0 index=3
共1*(10^3) = (0+1)*(10^3) = (hith+1)*(10^index) = 1000种可能
所以,当k<digit时,k出现次数为(hith+1)*(10^index)
四、当k=0时
由于没有0xxx,00xx,000x这种数字,
所以k=0时,在千位就比k等于其他数字少了1000次,在百位少100次,在十位少10次,
在个位时0000即为0,所以不比k等于其他数字时少
代码如下:
1 class Solution: 2 """ 3 @param: : An integer 4 @param: : An integer 5 @return: An integer denote the count of digit k in 1..n 6 """ 7 8 def digitCounts(self, k, n): 9 # k出现的次数 10 times = 0 11 12 quotient = n 13 # 将整数转为字符串后,利用 len() 判断 n 的位数 14 # i即为分析中的index 15 for i in range(len(str(n))): 16 # remainder 即为分析中的digit 17 remainder = quotient % 10 18 # 获得高位high 19 quotient = quotient // 10 20 power = pow(10, i) 21 22 if k > remainder: 23 times += quotient * power 24 elif k == remainder: 25 # 通过高位乘以10对应的(幂+1) 26 # 加上 digit乘以10对应的幂 27 # 获得与低位互补的新的高位 28 # 再用n减去新的高位,即可获得低位 29 new_quotient = quotient * power * 10 \ 30 + remainder * power 31 times += (quotient * power \ 32 + (n - new_quotient) \ 33 + 1) 34 else: 35 times += (quotient + 1) * power 36 37 if k == 0: 38 # 当k不在个位时,k出现次数要减去10对应的幂 39 if power != 1: 40 times -= power 41 42 return times