当前位置: 首页 > news >正文

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

一、题目描述

给你一个整数 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); 等语句展示了如何将计算结果赋值给数组元素。

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


http://www.mrgr.cn/news/41884.html

相关文章:

  • 【Java】—— 集合框架:Collection子接口:Set不同实现类的对比及使用(HashSet、LinkedHashSet、TreeSet)
  • 展示批量剪辑分割多个视频,助力轻松剪辑
  • 自研tauri‘2.0+vite5+elementPlus客户端exe聊天系统-源码版
  • YOLO11改进 | 卷积模块 | 添加选择性内核SKConv【附完整代码一键运行】
  • 征程6 工具链常用工具和 API 整理(含新手示例)
  • 动态规划
  • Macos终端常用的命令行指令总结
  • Nodejs多版本切换工具NVM
  • csdn加目录,标题
  • 主动配电网故障恢复的重构与孤岛划分模型——代码
  • 【艾思科蓝】Python数据分析与可视化实战:从入门到进阶
  • 【大数据入门 | Hive】函数{单行函数,集合函数,炸裂函数,窗口函数}
  • [RabbitMQ] Spring Boot整合RabbitMQ
  • 【含文档】基于Springboot+Vue的海洋馆预约系统(含源码+数据库+lw)
  • 【机器学习】集成学习——提升模型准确度的秘密武器
  • C++ 语言特性12 - 联合体类型
  • 【MySQL】SQL介绍+基础+DDL+数据备份+还原
  • SQL高级语法
  • 【python面试宝典3】遍历文件夹
  • PlantUML中的实体关系图