把只包含因子2、3和5的數稱作丑數(Ugly Number)。例如6、8都是丑數,但14不是,因為它包含因子7。
習慣上我們把1當做是第一個丑數。求按從小到大的順序的第N個丑數。
輸入包括一個整數N(1<=N<=1500)。
可能有多組測試數據,對於每組數據,
輸出第N個丑數。
3
3
最簡單的思路是,從1到大數,每個數都檢測一遍是否是丑數,檢測方法可以考慮
int ugly(int number){ if(number%2 == 0){ return ugly(number/2); }else if(number%3 == 0){ return ugly(number/3); }else if(number%5 == 0){ return ugly(number/5); }else return number==1?true:false; }
可是這種思路,會浪費大量的時間,最後就會超時。
我們考慮一個數組,數組存儲的是當前的丑數,以後的每個丑數,都是用之前的數組的元素相乘的來的。接下來就是如何得到後面的丑數並保證它是有序的。
可以想到,數組的第一個元素是1,1與2 3 5分別相乘,可以得到三個值,這三個值裡面最小的,肯定就是下一個丑數的最大值,接著max2的下標後移,繼續比較。
void mkUglyNumber(){ gArr[top++] = 1; int *max2 = gArr; int *max3 = gArr; int *max5 = gArr; while(top < 1500){ int min = getMin(*max2*2,*max3*3,*max5*5); gArr[top] = min; while(*max2*2 <= gArr[top]) ++max2; while(*max3*3 <= gArr[top]) ++max3; while(*max5*5 <= gArr[top]) ++max5; ++top; } }
比如,當前的數組元素只是1,那麼與2 3 5 相乘得到2 3 5,顯然得到的最小值是2。數組元素變為1 2。
下標這回變為2 1 1,繼續與2 3 5相乘,得到4 3 5,找出其中最小的,再放進數組,元素變為1 2 3。
繼續,直到找到1500個丑數之後,每次進行讀取丑數即可。
#include <stdio.h> #define MAXSIZE 1500 void mkUglyNumber(); int getMin(int max2,int max3,int max5); int gArr[MAXSIZE]; int top; int main(){ int n; top = 0; mkUglyNumber(); while(scanf("%d",&n)!=EOF && n>=1 && n<=1500){ printf("%d\n",gArr[n-1]); } return 0; } void mkUglyNumber(){ gArr[top++] = 1; int *max2 = gArr; int *max3 = gArr; int *max5 = gArr; while(top < 1500){ int min = getMin(*max2*2,*max3*3,*max5*5); gArr[top] = min; while(*max2*2 <= gArr[top]) ++max2; while(*max3*3 <= gArr[top]) ++max3; while(*max5*5 <= gArr[top]) ++max5; ++top; } } int getMin(int max2,int max3,int max5){ int min = max2<max3?max2:max3; return min<max5?min:max5; } /************************************************************** Problem: 1214 User: xhalo Language: C Result: Accepted Time:10 ms Memory:920 kb ****************************************************************/