面試題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 在數值之前可能有乙個表示正負的 或者 接下來是若干個...