LintCode Python解法

3.统计数字(Digit Count)git

计算数字 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))的解法,搞懂思路后,终于本身实现了markdown

本题求k出现的次数,其实能够等价于求k在各个数位上出现的次数之和app

以n=3154为例,分状况讨论spa

设k所在数位为index(好比k在千位,index就是3;k在百位,index就是2)设计

设digit为k所在数位上,n对应的数值(好比k在千位,digit就是3;k在百位,digit就是1)code

设k所在数位前的数为高位high,k所在数位后的数为低位low(好比k在百位,high就是3,low就是54;k在十位,high就是31,low就是4)blog

1、当k>digit时ip

  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)

2、当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

3、当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)

 4、当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

 

4. 丑数II(ugly number ii)

设计一个算法,找出只含素因子235 的第 n 小的数。

符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12...

 

解决本题的思路是,除了1之外,题目要求的丑数只含有2,3,5这3种质因子,因此后面的丑数都是前面的丑数乘以2,3,5获得的

原问题转化为求一个数列中,第n个丑数如何得到的问题

假设长度为n-1的丑数数列第一个数为uglys[1] = 1

设2*uglys[i] > uglys[n-1], 3*uglys[j] > uglys[n-1], 5*uglys[k] > uglys[n-1] (注意,这里的n-1表示第n-1个数,跟列表里的下标不同)

若是i,j,k分别是知足上述不等式的最小整数,那么uglys[n] = min(2*uglys[i], 3*uglys[j], 5*uglys[k])

很显然,i,j,k大多时候是不一样的,因此咱们要设置3个下标来分别记录他们在数组中的位置

代码以下:

 1 class Solution:  2 """  3  @param n: An integer  4  @return: return a integer as description.  5 """  6 def nthUglyNumber(self, n):  7 uglyNumers = [1]  8  9 i2, i3, i5 = 0, 0, 0 10 num2, num3, num5 = uglyNumers[i2] * 2, \ 11 uglyNumers[i3] * 3, \ 12 uglyNumers[i5] * 5 13 # 虽然形式是双重循环 14 # 可是里面的3个while每次最多各执行一次 15 # 因此时间复杂度是O(n) 16 while len(uglyNumers) < n: 17 while num2 <= uglyNumers[-1]: 18 i2 += 1 19 num2 = uglyNumers[i2] * 2 20 while num3 <= uglyNumers[-1]: 21 i3 += 1 22 num3 = uglyNumers[i3] * 3 23 while num5 <= uglyNumers[-1]: 24 i5 += 1 25 num5 = uglyNumers[i5] * 5 26  uglyNumers.append(min(num2, num3, num5)) 27 return uglyNumers[-1]
相关文章
相关标签/搜索