劍指 Offer 49 醜數(三指標)

2022-07-13 05:39:12 字數 1536 閱讀 3209

我們把只包含質因子 2、3 和 5的數稱作醜數(ugly number)。求按從小到大的順序的第 n 個醜數。

示例:輸入: n = 10輸出: 12解釋: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10個醜數。

說明:  

1是醜數。

n 不超過1690。

這道題很容易想到的是,醜叔的集合是dp[i]=dp[a] *2+dp[b]*3+dp[c]*5,即醜叔一定是2 3 5 的倍數,但如何保證從小到大生成這些有序的醜數呢,那我們其實很容易想到三指標,這三個指標分別指向2的乘數,3的乘數和5的乘數。

我們知道,醜數的排列肯定是1,2,3,4,5,6,8,10.... 然後有乙個特點是,任意乙個醜數都是由小於它的某乙個醜數*2,*3或者*5得到的,那麼如何得到所有醜數呢? 現在假設有3個陣列,分別是: a:

b:c:

那麼所有醜數的排列,必定就是上面abc3個陣列的合併結果然後去重得到的,那麼這不就轉換成了三個有序陣列的無重複元素合併的問題了嗎?而這三個陣列就剛好是乘以2,3,5得到的。

合併有序陣列的乙個比較好的方法,就是每個陣列都對應乙個指標,然後比較這些指標所指的數中哪個最小,就將這個數放到結果陣列中,然後該指標向後挪一位。

回到本題,要求醜數ugly陣列中的第n項,而目前只知道ugly[0]=1,所以此時三個有序鍊錶分別就只有乙個元素:

a :

b :

c :假設三個陣列的指標分別是i,j,k,此時均是指向第乙個元素,然後比較a[i],b[j]和c[k],得到的最小的數a[i],就是ugly[1],此時ugly就變成了,對應的abc陣列就分別變成了:

a :

b :

c :此時根據合併有序陣列的原理,a陣列指標i就指向了下乙個元素,即'2*2',而j和k依然分別指向b[0]和c[0],然後進行下一輪合併,就是a[1]和b[0]和c[0]比較,最小值作為ugly[2].....如此迴圈n次,就可以得到ugly[n]了。

此外,注意到abc三個陣列實際上就是ugly*2,ugly*3和ugly*5的結果,所以每次只需要比較a[i]=ugly[i]*2,b[j]=ugly[j]*3和c[k]=ugly[k]*5的大小即可。然後誰最小,就把對應的指標往後移動乙個,為了去重,如果多個元素都是最小,那麼這多個指標都要往後移動乙個。

class

solution

def nthuglynumber(self, n: int) ->int:

dp = [1] *n

a, b, c =0 ,0 ,0

for i in range(1, n):

dp[i] = min(dp[a]*2, dp[b]*3, dp[c]*5)

if dp[i] == dp[a]*2:

a += 1 #為什麼a要加1,這是為了遞增a

if dp[i] == dp[b]*3:

b += 1

if dp[i] == dp[c]*5:

c += 1

return dp[-1]

時間複雜度o(n)

空間複雜度o(1)

劍指Offer 49 醜數

我們把只包含因子2 3和5的數稱為醜數。求按從小到大的順序的第1500個醜數。例 6 8都是醜數,但14不是,因為它包含因子7。習慣上我們把1當作第乙個醜數。遍歷數字,對每個數字判斷是否只包含2 3 5因子。問題在於,有很多無用的計算,增加時間複雜度。時間複雜度 o n 空間複雜度 o 1 可以發現...

劍指offer49 醜數

把只包含質因子2 3和5的數稱作醜數 ugly number 例如6 8都是醜數,但14不是,因為它包含質因子7。習慣上我們把1當做是第乙個醜數。求按從小到大的順序的第n個醜數。思路 1.每次找出乙個最小丑數res i 都會產生三個新的醜數,2 res i 3 res i 5 res i 2.如果我...

劍指 Offer 49 醜數

我們把只包含質因子 2 3 和 5 的數稱作醜數 ugly number 求按從小到大的順序的第 n 個醜數。出看這道題可能感覺能算,但是思路就非常繁瑣。解法一 這個只說說思路,既然2,3,5是該數的因子,那麼該數除以2,3,5的餘數一定是 0 那麼就讓每個數連續除以2,3,5,只到餘數不為0 結果...