劍指offer 5 3 時間與空間效率平衡 醜數

2021-06-23 04:17:29 字數 2038 閱讀 5359

面試題34:醜數

我們把只包含因子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)

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

int getuglynumber_solution1(int index)

}return number;

}

問題是:每個整數都需要計算,即使乙個數字不是醜數,我們也要對其進行求余計和

除法計算,效率不是很高。

解法二:

根據醜數的定義,醜數應該是另乙個醜數乘以2、3或者5的結果(1除外)。

因此我們可以建立乙個陣列,裡面的數字是排好序的醜數。裡面的每乙個醜數是前面的醜數乘以2、

3或者5得到的。

思路的關鍵:怎樣確保陣列中的醜數是排好序的。

假設陣列中已經有若干個醜數,排好序後存放在陣列中。現有的最大的醜數記作m.

現在,開始生成下乙個醜數,該醜數是前面某乙個醜數乘以2、3或5的結果。

首先考慮把已有的每個醜數乘以2,在乘以2的時候,能得到若干個結果小於或等於m的。由於是按照順序生成的,小於或者等於m的數肯定已經在陣列中了,不需要再次考慮;而得到的若干個大於m的結果,只需要第乙個大於m的結果,記為m2;

按照同樣的方法,把已有的醜數成以3和5,得到第乙個大於m的結果m3和m5;

那麼下乙個醜數可定時m2\m3\m5中最小的。

根據前面的分析,把已有的每個醜數乘以2、3、5,事實上是不必要的,因為已有的醜數是按順序在陣列中的。對乘以2而言,肯定存在某乙個醜數t2,排在t2之前的每乙個醜數乘以2得到的結果都會小於已有的最大的醜數,在t2之後的每個醜數乘以2得到的結果都會大於已有的最大醜數。

只需要記下這個醜數t2的位置,同時每次生成新醜數的時候,去更新這個t2,對3和5而言,同樣存在這t3和t5.

//獲取第k個醜數,假定1為第乙個醜數

int findindexthuglynumber2(int index)

{ //如果index<=0表明輸入有誤,直接返回0

if(index<=0)

return 0;

//定義醜數陣列,用於記錄排序的醜數

int *puglynumbers=new int[index];

//第乙個醜數為1

puglynumbers[0]=1;

//第乙個醜數的座標是0,下乙個醜數的座標從1開始

int nextuglyindex=1;

//定義三個指向醜數陣列的指標,用它們來標識從陣列中的哪乙個數開始計算m2,m3和m5,開始都是醜數陣列的首位址。

int *t2=puglynumbers;

int *t3=puglynumbers;

int *t5=puglynumbers;

while(nextuglyindex和第一種思路相比,這種演算法不需要在非醜數的整數上做任何計算,因此時間複雜度要低很多。

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

劍指offer53 矩形覆蓋

我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋乙個2 n的大矩形,總共有多少種方法?比如n 3時,2 3的矩形塊有3種覆蓋方法 實質上是斐波那契數列的思想。第乙個填滿,即豎著放的時候,還剩下f n 1 種放法。第乙個橫著放的時候,即兩個橫著放的時候,還剩下f ...

劍指offer 53 表示數值的字串

請實現乙個函式用來判斷字串是否表示數值 包括整數和小數 例如,字串 100 5e2 123 3.1416 和 1e 16 都表示數值。但是 12e 1a3.14 1.2.3 5 和 12e 4.3 都不是。本題的主要解題思路如下 首先判斷字串是否為空,或者首元素是否為 若是是則直接返回false 否...

劍指offer 53 表示數值的字串

題目描述 請實現乙個函式用來判斷字串是否表示數值 包括整數和小數 例如,字串 100 5e2 123 3.1416 和 1e 16 都表示數值。但是 12e 1a3.14 1.2.3 5 和 12e 4.3 都不是。輸出描述 true false 在數值之前可能有乙個表示正負的 或者 接下來是若干個...