问题描述:
解决方案:
自己的方法:
就是先判断一个数字是不是丑数,如果是,n--。
但是这个题目要求输出第n个丑数,不是输入0-n中有多少个丑数。
所以我打算来一个数字num从0开始加,如果数字num是丑数,n-- ,num++,如果不是丑数,就num++.一直到n=0是,输出num.
接下来就是判断,一个数字num是否为丑数了,为此专门写一个函数isUgly()做判断
所谓一个数m是另一个数n的因子,是指n能被m整数,n%m==0。
如果num可以被2,3,5任意一个数整除,那么就接着,把其商作为num, 再接着做除法。 类似于辗转相除法。
一直除到num=1,则就是丑数
如果不能被2,3,5整除,那么就不是丑数。
代码如下:
class Solution {
public:
bool isUgly(int x)
{
//判断数x是否为丑数
while(x%2==0) x=x/2;
while(x%3==0) x=x/3;
while(x%5==0) x=x/5;
if(x==1) return true;
else return false;
}
int nthUglyNumber(int n) {
if(n<0)
{
return 0;
}
int num=1;
while(n>=0)
{
bool flag=isUgly(num);
if (flag)
{
n--;
}
if(n==0){
return num;
}
num++;
}
return 0;
}
};
结果就是:n比较小的时候,可以出结果,但是n比较大的时候,就超出时间限制了。
这是因为,不管一个数是否为丑数,我们都对其做了除法运算。
看书看题解得到别人的方法:
根据丑数的定义,一个新的丑数,应该是另外一个丑数,乘以2,3或者5得到的。
所以我们将现有的丑数放在一个有序的数组中(从小到大),那么新的丑数一定是某个现有的丑数x,乘以2,3,5得到的。
至于如何找这个丑数x,我们可以反过来想
任何一个丑数,乘以2,3,5 都可以得到一个新的丑数。
我们把乘以2的数字,记作a,乘以3的数字记作b,乘以5的数字记作c(其实就是理解为dp[a],dp[b],dp[c])
最开始a,b,c都初始化为0,
如果有一个丑数,是乘以a得到的,则a就加1.
注意!注意! 类似于6这个数字,可以理解为2*3,也可以理解为3*2,这个时候a,b都需要加1.
所以设置的都是if 语句,不是if else 语句。
之后的代码:
class Solution {
public:
int nthUglyNumber(int n) {
//有序数组
if(n<=0){
return n;
}
int dp[n];
dp[0]=1;
int a=0,b=0,c=0;
for(int i=1;i<n;i++)
{
int x1=2*dp[a],x2=3*dp[b],x3=5*dp[c];
dp[i]=min(min(x1,x2),x3);
if(dp[i]==x1) a++;
if(dp[i]==x2) b++;
if(dp[i]==x3) c++;
}
return dp[n-1];
}
};
结果: