题目描述:
解题思路:
解题目思路一: 动态规划
- 丑数的递推性质: 丑数只包含因子 2, 3, 5,因此有 “丑数 == 某较小丑数× 某因子” (例如:10 = 5×2)。
文字描述:
- 根据丑数的定义,丑数应该是由另一个丑数乘以2或者3或者5得到的结果(1除外),因此,我们就可以去创建一个数组,里面的数字是排好序的丑数,每个丑数都是前面的丑数乘以2或者3或者5得到的结果
- 这种思路的官见在于则囊确保数组里面的丑数是排好序的丑数,并把已有的最大丑数记作M,接下来分析如何产生下一个丑数,该丑数肯定是前面某一个丑数乘以2或者3或者5从而得到的结果,所以我们优先考虑把已经存在的丑数乘以2,在乘以2 的时候,能得到若干个小于或者等于M的丑数,由于是按照顺序生成的,小于或等于M的已经是存在在数组当中的了,我们不需要去再次考虑,同时还会得到若干个大于M的结果,但是我们只需要第一个大于M的结果,因为我们希望丑数是从小到大生成的,其他的更大的结果以后再说,3和5是同样的道理
复杂度分析:
- 时间复杂度 O(N),其中 N = n,动态规划需遍历计算 dpdp 列表。
- 空间复杂度 O(N), 长度为 Ndp 列表使用 O(N)的额外空间。
代码如下所示:
代码一:
class Solution {
public:
bool Is_Find(int number)
{
while(number%2==0)
{
number/=2;
}
while(number%3==0)
{
number/=3;
}
while(number%5==0)
{
number/=5;
}
return (number==1)?true:false;
}
int GetUglyNumber_Solution(int index)
{
if(index<=0)
return 0;
int found=0;
int number=0;
while(found<index)
{
++number;
if(Is_Find(number))
{
++found;
}
}
return number;
}
};
- 但是上面的这个代码,算法的时间复杂度有一些大,所以无法在通过检测,因为时间复杂度有些大,所以会超出时间的限制。
class Solution {
public:
int GetUglyNumber_Solution(int index)
{
if(index==0)
return 0;
int a=0;
int b=0;
int c=0;
int dp[index];
dp[0]=1;
for(int i=1;i<index;i++)
{
dp[i]=min(dp[a]*2,min(dp[b]*3,dp[c]*5));
if(dp[i]==dp[a]*2)
a++;
if(dp[i]==dp[b]*3)
b++;
if(dp[i]==dp[c]*5)
c++;
}
return dp[--index];
}
};
测试用例
- 功能测试(输入2,3,4,5,6,等数字)
- 特殊输入测试(边界值1,无效输入值0)
- 性能测试(输入较大的数字,如190)