什么是丑數:
一個數的因子僅僅包括2,3,5的數稱為丑數。數字1特別對待也看作是丑數,所以從1開始的10個丑數分別為1,2。3。4,5,6,8,9。10。12。
因子的概念:
整數m除以n,得到無余數的商,則稱n是m的一個因子。如8的因子有1、2、4、8。而丑數要求的因子僅僅包括2、3、5。所以丑數中的因子應理解為質因子。
即因子為質數。質數又稱素數,指一個大於1的自然數。除了1和它自身外,不能被其它自然數整除的數。
與質數相相應的數稱為合數。
如今要求寫一個程序,輸出從1開始的第N個丑數。
如第一個丑數為1,第二個丑數為2。第十個丑數為12
推斷是否是丑數的算法:
設待推斷整數位M,M循環除以2直到不能整除。此時接着循環除以3直到不能整除。接着循環除以5直到商為1或者不能整除為止。
商為1且余數為0則為丑數,否則為非丑數。
如:丑數12
12/2 = 6
6/2 = 3;
3/2 不能整除
3/3 = 1; 結束,12是丑數
非丑數26
26/2 = 13
13/2 不能整除
13/3 不能整除
13/5 不能整除
結束,26不是整數
尋找丑數算法1:
(1)設置一個計數器用來統計出現的丑數的個數
(2)從1開始遍歷每個整數,推斷是否是丑數,假設是丑數則計數器加1。否則遍歷下一個整數。
(3)當計數器的值=N時,停止遍歷。輸出丑數。
#include <stdio.h>
#include <time.h>
#include <string.h>
int isUgly(int number){ //推斷number是否是丑數
while(number%2==0){ //推斷數是否能被2整除
number=number/2;
}
while(number%3==0){ //推斷數是否能被3整除
number=number/3;
}
while(number%5==0){ //推斷數是否能被5整除
number=number/5;
}
if(number == 1) //
return 1;
else
return 0;
}
int findUgly(int N){ //尋找從1開始的第N個丑數
int count=0; //用於計數
int number=1; //從1開始遍歷
while(1){
if(isUgly(number)){ //假設number是丑數計數器加1
count++;
}
if(count == N) //找到第N個丑數,返回丑數
return number;
else
number++;
}
}
void main(){
int N=0;
scanf("%d",&N);
clock_t start = clock();
printf("%d\n",findUgly(N));
clock_t stop = clock();
printf("耗時:%lf\n",(double)(stop - start) / CLOCKS_PER_SEC);
}
上面算法從1開始遍歷,來尋找第N個丑數,當N非常大時花費的時間會非常多。當N為1400的時候消耗23秒。隨着N的增大。耗時相當嚴重

尋找丑數算法2:
想辦法從上一個丑數判斷出下一個丑數,而不須要從1開始遍歷再判斷。從1開始的10個丑數分別為1,2。3,4,5,6,8。9。10。12。
能夠發現除了1以外。丑數都是由某個丑數*2或者*3或者*5得到的。
如2是丑數1*2得到的,3是丑數1*3得到的。4是丑數1*4得到的。5是丑數1*5得到的。6是丑數2*3得到的……
詳細算法步驟:
(1)從第一個丑數1開始,求出1*2=2 ,1*3=3 ,1*5 = 5。
(2)取上面乘積中大於1的最小值2,作為第二個丑數(丑數是個遞增序列。所以第i+1個丑數一定比第i個丑數)
(3)求丑數2之前的丑數與2、3、5的乘積:1*2=2 ,1*3=3 ,1*5 = 5; 2*2 = 4; 2*3 = 6。 2*5 =10。
(4)取上面乘積中大於2的最小值3,作為第三個丑數
……
……
(i)取出丑數i之前的丑數分別與2、3、5的乘積
(i+1)取乘積中大於i的最小值作為丑數
(i+2)反復(i)(i+1)的步驟直到計數器等於N
#include <stdio.h>
#include <time.h>
#include <string.h>
#define MaxLen 99999
//用於求出3個數的最小值
int compare(int chenTwo,int chenThree,int chenFive){
if(chenTwo <=chenThree){
if(chenTwo <= chenFive)
return chenTwo;
else
return chenFive;
}
else if(chenThree <= chenFive)
return chenThree;
else
return chenFive;
}
//找出第N個丑數
int findUgly(int N){
int ugly[MaxLen]={1}; //用於保存丑數的數組,將丑數1存入數組中
int count=1; //數組中僅有丑數1,所以計數器為1
while(1){
int chenTwo = 0;
int chenThree = 0;
int chenFive = 0;
/*
ugly數組中最新的一個丑數為ugly[count-1],
ugly[count-1]之前的丑數與2相乘,
求出第一個乘積大於ugly[count-1]的值保存在chenTwo中
*/
for(int i = 0 ; i < count ; i++){
if(ugly[i]*2 >ugly[count-1]){
chenTwo = ugly[i]*2;
break;
}
}
/*
ugly數組中最新的一個丑數為ugly[count-1],
ugly[count-1]之前的丑數與3相乘,
求出第一個乘積大於ugly[count-1]的值保存在chenThree中
*/
for(i = 0 ; i < count ; i++){
if(ugly[i]*3 >ugly[count-1]){
chenThree = ugly[i]*3;
break;
}
}
/*
ugly數組中最新的一個丑數為ugly[count-1],
ugly[count-1]之前的丑數與5相乘,
求出第一個乘積大於ugly[count-1]的值保存在chenFive中
*/
for(i = 0 ; i < count ; i++){
if(ugly[i]*5 >ugly[count-1]){
chenFive = ugly[i]*5;
break;
}
}
//chenTwo,chenThree。chenFive的最小值為新的丑數,存入ugly數組中
ugly[count]=compare( chenTwo, chenThree, chenFive);
count++;
if(count==N) //第N個丑數
return ugly[count-1];
}
}
void main(){
int N=0;
scanf("%d",&N);
clock_t start = clock();
printf("%d\n",findUgly(N));
clock_t stop = clock();
printf("耗時:%lf\n",(double)(stop - start) / CLOCKS_PER_SEC);
}
當輸入N=1400時,耗時還不足0.1秒。可見算法2的速度是算法1所不能比擬的,這是用空間來換取效率的結果。

