文章目录
- 一【题目类别】
- 二【题目难度】
- 三【题目编号】
- 四【题目描述】
- 五【题目示例】
- 六【解题思路】
- 七【题目提示】
- 八【时间频度】
- 九【代码实现】
- 十【提交结果】
一【题目类别】
- 动态规划
二【题目难度】
- 中等
三【题目编号】
- 264.丑数 II
四【题目描述】
- 给你一个整数 n ,请你找出并返回第 n 个 丑数 。
- 丑数 就是只包含质因数 2、3 和 5 的正整数。
五【题目示例】
-
示例 1:
- 输入:n = 10
- 输出:12
- 解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
-
示例 2:
- 输入:n = 1
- 输出:1
- 解释:1 通常被视为丑数。
六【解题思路】
- 如果判断每一个数字是否是丑数,肯定会超时,所以应该使用题目给的条件,生成丑数,这就用到了动态规划的知识
- 由于第一个丑数我们是知道的,应该是1,那么就利用1来生成剩余的丑数
- 因为丑数只包含2、3、5,所以用丑数乘这几个数还是丑数,那么究竟乘哪个呢?肯定每次都要取乘完之后最小的
- 所以定义三个指针,分别表示三个丑数因数该乘哪个丑数了
- 这样每次都用没乘过2或3或5的最小丑数,乘2或3或5,就可以得到新的丑数,所以动态转移方程为: d p [ i ] = m i n ( d p [ p 2 ] ∗ 2 , d p [ p 3 ] ∗ 3 , d p [ p 5 ] ∗ 5 ) dp[i] = min(dp[p2] * 2,dp[p3] * 3,dp[p5] * 5) dp[i]=min(dp[p2]∗2,dp[p3]∗3,dp[p5]∗5)
- 还要注意,每次乘完2或3或5后,对应的指针应该后移,表示当前已经得到一个最小的丑数了,应该去比较下一个丑数与2或3或5相乘会不会得到最小丑数
- 最后返回结果即可
七【题目提示】
- 1 < = n < = 1690 1 <= n <= 1690 1<=n<=1690
八【时间频度】
- 时间复杂度: O ( n ) O(n) O(n),其中 n n n为传入参数大小
- 空间复杂度: O ( n ) O(n) O(n),其中 n n n为传入参数大小
九【代码实现】
- Java语言版
class Solution {
public int nthUglyNumber(int n) {
int[] dp = new int[n + 1];
dp[1] = 1;
int p2 = 1;
int p3 = 1;
int p5 = 1;
for(int i = 2;i<=n;i++){
dp[i] = Math.min(dp[p2] * 2,Math.min(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];
}
}
- C语言版
int nthUglyNumber(int n)
{
int* dp = (int*)malloc(sizeof(int) * (n + 1));
dp[1] = 1;
int p2 = 1;
int p3 = 1;
int p5 = 1;
for(int i = 2;i<=n;i++)
{
dp[i] = fmin(dp[p2] * 2,fmin(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];
}
- Python版
class Solution:
def nthUglyNumber(self, n: int) -> int:
dp = [1] * (n + 1)
p2 = 1
p3 = 1
p5 = 1
for i in range(2,n+1):
dp[i] = min(dp[p2] * 2,dp[p3] * 3,dp[p5] * 5)
if dp[i] == dp[p2] * 2:
p2 += 1
if dp[i] == dp[p3] * 3:
p3 += 1
if dp[i] == dp[p5] * 5:
p5 += 1
return dp[n]
十【提交结果】
-
Java语言版
-
C语言版
-
Python语言版