题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路如下:
1. 除1之外,所有的丑数都是前面某个丑数乘2或乘3或乘5的结果
2. 动态规划的思想
dp[i] = min(dp[x]*2, dp[y]*3, dp[z]*5)
其中 dp[x]*2 表示序列 [dp[0]*2, dp[1]*2, dp[2]*2... dp[i-1]*2] 中第一个大于dp[i-1]的值, dp[y]*3和dp[z]*5类似
代码如下:
class Solution {
public:
//除1之外,所有的丑数都是前面某个丑数乘2或乘3或乘5的结果
//动态规划的思想
// dp[i] = min(dp[x]*2, dp[y]*3, dp[z]*5) 其中dp[x]*2,dp[y]*3, dp[z]*5都大于dp[i-1]
int get_ugly_number(int index){
if(0 == index){
return 0;
}
vector<int> dp(index);
dp[0] = 1;
int dp2 = 0;
int dp3 = 0;
int dp5 = 0;
for(int i = 1; i < index; ++i){
for(int j = 0; j < i; ++j){ //从dp[0]到dp[i-1]分别乘以2
dp2 = dp[j]*2;
if(dp2 > dp[i-1]) break; //取第一个大于dp[i-1]的值
}
for(int j = 0; j < i; ++j){
dp3 = dp[j]*3;
if(dp3 > dp[i-1]) break;
}
for(int j = 0; j < i; ++j){
dp5 = dp[j]*5;
if(dp5 > dp[i-1]) break;
}
dp[i] = min(dp2, min(dp3, dp5)); //dp[i]为三者中的最小值
}
return dp[index-1];
}
//优化上面的算法
//观察上面算法中第一层for循环内的三个for循环, 每次都从0开始计算,会有很多重复计算
//dp[i] = min(dp[x]*2, dp[y]*3, dp[z]*5) 其中dp[x]*2,dp[y]*3, dp[z]*5都大于dp[i-1]
//可以设置三个指针x,y,z, x指向当前要乘2的最小丑数, y z类似
//如果dp[x]*2是最小丑数,则x++
int get_ugly_number_better(int index){
if (0 == index){
return 0;
}
vector<int> dp(index);
dp[0] = 1;
int x = 0;
int y = 0;
int z = 0;
for(int i = 1; i < index; i++)
{
int a = dp[x]*2;
int b = dp[y]*3;
int c = dp[z]*5;
dp[i] = min(a, min(b, c));
if(dp[i] == a) x++;
if(dp[i] == b) y++;
if(dp[i] == c) z++;
}
return dp[index-1];
}
int GetUglyNumber_Solution(int index) {
//return get_ugly_number(index);
return get_ugly_number_better(index);
}
};