劍指offer 49題 醜數

2021-09-25 12:57:28 字數 2111 閱讀 3782

首先醜數m就是能被n(2、3、5)整除,即m%n == 0;所以我們可以對每個數來逐一判斷是不是可以被2、3、5整除。

//判斷乙個數是不是醜數

bool ugly(int m)

while(m%3 == 0)

while(m%5 == 0)

return (m==1) ? true : false;

}int getungly1(int index)

int i =0;

int count = 0;//count用來記錄醜數的個數

while(count < index) }

return i;

}

第一種思路很簡單,但是他需要對每乙個數(不管是不是乙個醜數都要進行操作)都進行判斷,進行求餘和除法操作,時間複雜度高。

思路一是不管是不是乙個醜數都要進行操作,為了改進,我們可以只對醜數進行操作。醜數的因子是由2、3、5構成的,所以乙個醜數乘2、3或者5也必為醜數。所以我們可以建立乙個陣列,裡面放好排好序的醜數,每乙個醜數都是前面的醜數乘2、3或5得到的。

那麼如何確保陣列裡的醜數都有序呢,假設已經有乙個含有若干個排好序的醜數的陣列,陣列中最大醜數記為m。那麼下乙個醜數肯定是前面某乙個醜數乘2、3或者5的結果。我們先讓前面的醜數都乘2,(由於是排好序的陣列,所以m*2生成的結果也是排好序的)得到的結果會有一部分小於等於醜數m,一部分大於醜數m。小於等於m的結果肯定已經在陣列中了我們不在考慮,我們只看大於m的結果,但是我們只取第乙個大於m的結果,記為m2。之後再讓前面的醜數分別與3、5相乘,都只取第乙個大於m的結果,記為m3,m5。那麼下乙個醜數就為m2,m3,m5中最小的那個。

根據上圖,我們發現當我們再繼續找6之後的醜數的時候,再去將前面的醜數挨個乘2、3或者5的時候,就重複計算了。因為我們對前面的醜數分別乘2、3、5的時候,會有乙個臨界點,在這個醜數之前進行乘法操作都是<=m,在這個醜數之後進行乘法操作都》m,所以我們需要乙個指標來記錄這個臨界點的位置,在這個臨界點之前的醜數我們就不再對他們進行乘法操作了(因為他總是小於等於m,並且陣列是按順序排列的),同時每次生成新的醜數的時候再去更新這個臨界點的位置即可。我們用t2、t3、t5來表示這個位置。其實這個臨界點的位置所存放的資料也就是我們要的第乙個比m大的醜數。

**實現:

//三個數中取最小

int min(int a,int b,int c)

else }

int getugly2(int index)

int *p = new int[index];//開闢記憶體

p[0] = 1;

int nextunglyindex = 1;//定義下乙個醜數下標

//定義指標來指向臨界點的位置,初始化都指向陣列的首元素

int *t2 = p;

int *t3 = p;

int *t5 = p;

while(nextunglyindex < index)

int ugly = p[nextunglyindex-1];//因為while迴圈中nextunglyindex多加了1,之後不符合while條件沒有進入迴圈,所以此時這個nextunglyindex是沒有放資料的,故減一

delete p;//釋放記憶體

return ugly;

}

和第一種思路相比,第二種時間效率有提高,但是由於需要儲存已經生成的醜數,需要乙個陣列,從而增加了空間的消耗,以空間換時間。

測試**:

int main()

{ for(int i = 0;i<10;i++)

{ cout<

劍指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 結果...