每天一道演算法題19 尋找醜數

2021-06-18 00:26:50 字數 1869 閱讀 3751

原文:

題目:我們把只包含因子2、

3和5的數稱作醜數(ugly number)

。例如6、8

都是醜數,但

14不是,因為它包含因子

7。習慣上我們把

1當做是第乙個醜數。求按從小到大的順序的第

1500

個醜數。

分析:這是一道在網路上廣為流傳的面試題,據說google曾經採用過這道題。

所謂乙個數m是另乙個數n的因子,是指n能被m整除,也就是n % m == 0。根據醜數的定義,醜數只能被2、3和5整除。也就是說如果乙個數如果它能被2整除,我們把它連續除以2;如果能被3整除,就連續除以3;如果能被5整除,就除以連續5。如果最後我們得到的是1,那麼這個數就是醜數,否則不是。

基於前面的分析,我們可以寫出如下的函式來判斷乙個數是不是醜數:

bool

isugly(int number)

接下來,我們只需要按順序判斷每乙個整數是不是醜數,即:

intgetuglynumber_solution1(int index)

} return number; }

我們只需要在函式getuglynumber_solution1中傳入引數1500,就能得到第1500個醜數。該演算法非常直觀,**也非常簡潔,但最大的問題我們每個整數都需要計算。即使乙個數字不是醜數,我們還是需要對它做求餘數和除法操作。因此該演算法的時間效率不是很高。

接下來我們換一種思路來分析這個問題,試圖只計算醜數,而不在非醜數的整數上花費時間。根據醜數的定義,醜數應該是另乙個醜數乘以2、3或者5的結果(1除外)。因此我們可以建立乙個陣列,裡面的數字是排好序的醜數。裡面的每乙個醜數是前面的醜數乘以2、3或者5得到的。

這種思路的關鍵在於怎樣確保陣列裡面的醜數是排好序的。我們假設陣列中已經有若干個醜數,排好序後存在陣列中。我們把現有的最大醜數記做m。現在我們來生成下乙個醜數,該醜數肯定是前面某乙個醜數乘以2、3或者5的結果。我們首先考慮把已有的每個醜數乘以2。在乘以2的時候,能得到若干個結果小於或等於m的。由於我們是按照順序生成的,小於或者等於m肯定已經在陣列中了,我們不需再次考慮;我們還會得到若干個大於m的結果,但我們只需要第乙個大於m的結果,因為我們希望醜數是按從小到大順序生成的,其他更大的結果我們以後再說。我們把得到的第乙個乘以2後大於m的結果,記為m2

。同樣我們把已有的每乙個醜數乘以3和5,能得到第乙個大於m的結果m3

和m5。那麼下乙個醜數應該是m2

、m3和m5

三個數的最小者。

前面我們分析的時候,提到把已有的每個醜數分別都乘以2、3和5,事實上是不需要的,因為已有的醜數是按順序存在陣列中的。對乘以2而言,肯定存在某乙個醜數t2

,排在它之前的每乙個醜數乘以2得到的結果都會小於已有最大的醜數,在它之後的每乙個醜數乘以2得到的結果都會太大。我們只需要記下這個醜數的位置,同時每次生成新的醜數的時候,去更新這個t2

。對乘以3和5而言,存在著同樣的t3

和t5。

有了這些分析,我們不難寫出如下的**:

intgetuglynumber_solution2(int index)

int ugly = puglynumbers[nextuglyindex - 1];

delete puglynumbers;

return ugly; }

intmin(int number1, int number2, int number3)

和第一種思路相比,這種演算法不需要在非醜數的整數上做任何計算,因此時間複雜度要低很多。感興趣的讀者可以分別統計兩個函式getuglynumber_solution1(1500)

和getuglynumber_solution2(1500)的執行時間。當然我們也要指出,第二種演算法由於要儲存已經生成的醜數,因此需要乙個陣列,從而需要額外的記憶體。第一種演算法是沒有這樣的記憶體開銷的。

每天一道演算法題 醜數

題目描述 把只包含因子2 3和5的數稱作醜數 ugly number 例如6 8都是醜數,但14不是,因為它包含因子7。習慣上我們把1當做是第乙個醜數。求按從小到大的順序的第n個醜數。分析 使用兩個佇列乙個存放節點,乙個存放值。先將根節點加入到佇列中,然後遍歷佇列中的元素,遍歷過程中,訪問該元素的左...

20190423 每天一道演算法題 醜數 (堆)

編寫乙個程式,找出第n個醜數。醜數就是只包含質因數2,3,5的正整數。示例 輸入 n 10,輸出 12 解釋 1,2,3,4,5,6,8,9,10,12,是前 10 個醜數。說明 1.1是醜數。2.n不超過1690。include includeint nthuglynumber int n voi...

每日一道演算法題 尋找醜數

題目 我們把只包含因子2 3和5的數稱作醜數 ugly number 例如6 8都是醜數,但14不是,因為它包含因子7。習慣上我們把1當做是第乙個醜數。求按從小到大的順序的第1500個醜數。分析 尋找乙個數是不是滿足某種數 質數,水仙數 等,最簡單的方法就是遍歷,對於任意乙個醜數必定可以寫成2 m ...