题目描述
把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思考
若判断一个数是不是丑数,可以知道一个丑数必然可以写成2^n1*3^n2*5^n3的形式,所以对一个数判断,可以不断分别对2,3,5取余,如果最后剩下的数为1则为丑数,否则则不是丑数。判断一个丑数的时间复杂度为O(lgn),求出第N个的时间复杂度为O(n*lgn);
另一种思考:
1.我们知道下一个丑数必定是前面的某个丑数的2,3,5的倍数,但是不确定是哪个。
2.丑数是不断递增的
3.1也是一个丑数
我们可以设定大小为N的数组,第一个数字为1。此时我们要求第二个丑数,我们很容易想到从1*2,1*3,1*5中选择,于是有2;
接下来,第三个丑数,可以想到是2*2,1*3,1*5中选择,于是有3;
所以我们可以设置三个指针point2,point3,point3,最开始都指向数组首元素,取指针指向的数分别乘以2,3,5,判断其是否大于当前数组最大元素,若否则指针前移,直到达到目标为止。于是此时我们可以得到三个数,只需要从这三个数中选取最小的数就可以。我们直到此时算法的时间复杂度大概为O(n);
代码如下:
int GetUglyNumber_Solution(int index) {
int ans[index];
ans[0]=1;
int *point2,*point3,*point5;
point2=&ans[0];point3=&ans[0];point5=&ans[0];
int nextindex=1;
while(nextindex<index)
{
while((*point2)*2<=ans[nextindex-1])
++point2;
while((*point3)*3<=ans[nextindex-1])
++point3;
while((*point5)*5<=ans[nextindex-1])
++point5;
ans[nextindex++]=Min((*point2)*2,(*point3)*3,(*point5)*5);
}
return ans[index-1];
}
int Min(int Num1,int Num2,int Num3)
{
if(Num1<Num2)
{
if(Num2<Num3)
return Num1;
else
return Num1<Num3?Num1:Num3;
}
else
{
if(Num1<Num3)
return Num2;
else
return Num2<Num3?Num2:Num3;
}}