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)
設計一個算法,找出只含素因子2
,3
,5
的第 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]