LeetCode题练习与总结:丑数 Ⅱ--264

223 篇文章 0 订阅
135 篇文章 0 订阅

一、题目描述

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是质因子只包含 23 和 5 的正整数。

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。

提示:

  • 1 <= n <= 1690

二、解题思路

  1. 创建一个动态规划数组 dp,其中 dp[i] 表示第 i 个丑数。初始化 dp[1] = 1,因为 1 通常被视为丑数。
  2. 创建三个指针 p2p3p5,分别表示下一个丑数可以通过乘以 2、3 或 5 得到。初始时,这三个指针都指向 1。
  3. 对于每个 i(从 2 到 n),计算 dp[i] 的值,它是 min(dp[p2] * 2, dp[p3] * 3, dp[p5] * 5)
  4. 更新 p2p3 和 p5 指针,以指向下一个应该乘以 2、3 或 5 的丑数。
  5. 返回 dp[n] 作为结果。

三、具体代码

class Solution {
    public int nthUglyNumber(int n) {
        int[] dp = new int[n + 1];
        dp[1] = 1;
        int p2 = 1, p3 = 1, p5 = 1;
        
        for (int i = 2; i <= n; i++) {
            int num2 = dp[p2] * 2, num3 = dp[p3] * 3, num5 = dp[p5] * 5;
            dp[i] = Math.min(Math.min(num2, num3), num5);
            
            if (dp[i] == num2) p2++;
            if (dp[i] == num3) p3++;
            if (dp[i] == num5) p5++;
        }
        
        return dp[n];
    }
}

在这个实现中,我们通过动态规划的方法,逐步构建出丑数序列。每个指针 p2p3p5 保证不会重复计算同一个丑数,并且能够保证丑数序列的顺序。

四、时间复杂度和空间复杂度

1. 时间复杂度
  1. 初始化 dp 数组需要 O(n) 的时间,因为需要将 dp[1] 设置为 1,其余 dp[i] 初始化为 0。
  2. 遍历 dp 数组,计算每个 dp[i] 的值,这个操作需要 O(n) 的时间,因为需要从 2 遍历到 n。
  3. 在每次遍历中,计算 num2num3num5 以及 Math.min 函数的调用都是常数时间操作,因此对于每次迭代,时间复杂度是 O(1)。
  4. 总的时间复杂度是 O(n) + O(n) * O(1) = O(n)。
2. 空间复杂度
  1. dp 数组需要 O(n) 的空间,因为需要存储 n 个丑数。
  2. 除了 dp 数组,我们只使用了几个额外的变量(p2p3p5num2num3num5),它们都是常数空间。
  3. 因此,总的空间复杂度是 O(n)。

五、总结知识点

  1. 类定义class Solution 定义了一个名为 Solution 的类。

  2. 方法定义public int nthUglyNumber(int n) 定义了一个公共方法 nthUglyNumber,它接受一个整数参数 n 并返回一个整数。

  3. 数组的使用int[] dp = new int[n + 1]; 创建了一个整数数组 dp,用于动态规划,长度为 n + 1 以存储从第 1 个到第 n 个丑数。

  4. 基本循环结构for (int i = 2; i <= n; i++) 使用了一个 for 循环来迭代数组 dp 的索引,从 2 到 n。

  5. 条件判断if (dp[i] == num2) p2++; 等条件判断用于检查当前的丑数是通过乘以 2、3 或 5 得到的,并相应地更新指针。

  6. 数学运算:使用乘法 * 和最小值函数 Math.min 来计算可能的丑数。

  7. 指针的概念p2p3p5 作为指针,分别跟踪下一个应该乘以 2、3 或 5 的丑数的位置。

  8. 数组的索引访问:通过 dp[p2]dp[p3]dp[p5] 等方式访问数组元素,以计算下一个可能的丑数。

  9. 变量赋值dp[i] = Math.min(Math.min(num2, num3), num5); 等语句展示了如何将计算结果赋值给数组元素。

以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一直学习永不止步

谢谢您的鼓励,我会再接再厉的!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值