题目描述
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
说明:
1 是丑数。
n 不超过1690。
题解思路
方法一:原始思路
逐个判断每个数是不是丑数,直到丑数的数量达到 n。该方法会超时!!!
class Solution {
public:
bool determine(int num){
if(num > 0 && num <= 6) return true;
else if(num < 0) return false;
while(num % 5 == 0) num /= 5;
while(num % 3 == 0) num /= 3;
while(num % 2 == 0) num /= 2;
return num == 1;
}
int nthUglyNumber(int n) {
int count = 0;
int i = 0;
while(count != n){
if(determine(++i)) ++count;
}
return i;
}
};
方法二:动态规划
上面的方法之所以会超时,是因为我们把每个数都判断了一遍,不管这个数是不是丑数。但是本方法我们只计算丑数,从而大大提升了时间效率。缺点是需要开辟一个长度为 n 的数组来进行动态规划过程。具体思路如下:
- 首先我们要发现,任何一个丑数,都是可以由其前面的某个丑数乘2,或乘3,或乘5得到。
- 我们先建立一个长度为 n 的 dp 数组,dp[i] 表示第 i + 1 个丑数。
- 然后我们设立三个变量:p2, p3, p5,它们都代表 dp 数组中的索引。我们通过选取
dp[p2] * 2, dp[p3] * 3 和 dp[p5] * 5
中的最小值来确定下一个丑数的值。 - 当找到了下一个丑数后,假如这个丑数是由 p2 得来的,我们就 ++p2;假如是由 p3 得来的,我们就 ++p3;是由 p5 得来的,我们就 ++p5。这样就可以保证每个丑数都会被找出来。
代码实现:
class Solution {
public:
int nthUglyNumber(int n) {
int p2 = 0, p3 = 0, p5 = 0;
vector<int> dp(n);
dp[0] = 1;
for(int i = 1; i < n; ++i){
dp[i] = min(min(dp[p2]*2, dp[p3]*3), dp[p5]*5);
if(dp[i] == dp[p2]*2) ++p2;
if(dp[i] == dp[p3]*3) ++p3;
if(dp[i] == dp[p5]*5) ++p5;
}
return dp[n-1];
}
};
如有帮助到您,可以多多点赞、评论鼓励哟~~~