算法的学习笔记—丑数(牛客JZ49)
【摘要】 在程序设计和算法竞赛中,**丑数**问题是一个经典的动态规划题目。丑数(Ugly Number)定义为只包含质因子 2、3 和 5 的数。举例来说,数字 6(因子为 2 和 3)、数字 8(因子为 2)都是丑数,而数字 14 不是丑数,因为它包含质因子 7。在这种定义下,1 通常被视为第一个丑数。
😀前言
在程序设计和算法竞赛中,丑数问题是一个经典的动态规划题目。丑数(Ugly Number)定义为只包含质因子 2、3 和 5 的数。举例来说,数字 6(因子为 2 和 3)、数字 8(因子为 2)都是丑数,而数字 14 不是丑数,因为它包含质因子 7。在这种定义下,1 通常被视为第一个丑数。
🥰丑数
😊题目描述
把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。例如 6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 N 个丑数。
例子
- 输入:N = 10
- 输出:12
- 解释:前10个丑数依次是 [1, 2, 3, 4, 5, 6, 8, 9, 10, 12],因此第10个丑数为12。
😄解题思路
解决该问题的常见方法是动态规划。动态规划的基本思想是从第一个丑数开始,逐步生成下一个丑数,直到得到第 N 个。
核心思想
- 定义状态:使用一个长度为 N 的数组
dp
,其中dp[i]
表示从小到大第 i+1 个丑数。初始化dp[0] = 1
,即第一个丑数是 1。 - 生成丑数:由于丑数的定义,新的丑数可以通过已知的丑数乘以 2、3 或 5 来生成。因此,我们在每一步都计算下一个可以生成的丑数。
- 三个指针:维护三个指针
i2
,i3
,i5
,分别表示当前丑数数组中,乘以 2、3、5 后最小值的索引。每次选择这三个数中的最小值作为下一个丑数,并更新相应的指针。 - 避免重复:如果当前生成的丑数等于多个最小值中的某个,我们需要将对应的指针后移,避免重复计算。例如,如果
dp[i]
既是dp[i2] * 2
,又是dp[i3] * 3
,我们需要同时更新i2
和i3
。
💖代码实现
public int GetUglyNumber_Solution(int N) {
if (N <= 6)
return N; // 特殊情况:如果 N 小于等于6,直接返回 N,因为前6个丑数为 [1, 2, 3, 4, 5, 6]
int i2 = 0, i3 = 0, i5 = 0; // 初始化三个指针,分别指向当前乘以2、3、5的丑数索引
int[] dp = new int[N]; // 创建数组存储前N个丑数
dp[0] = 1; // 第一个丑数是1
for (int i = 1; i < N; i++) {
// 计算下一个可能的丑数,分别为2、3、5的倍数
int next2 = dp[i2] * 2, next3 = dp[i3] * 3, next5 = dp[i5] * 5;
// 当前丑数是这三个数中的最小值
dp[i] = Math.min(next2, Math.min(next3, next5));
// 如果当前最小值是乘以2得到的,更新指针i2
if (dp[i] == next2)
i2++;
// 如果当前最小值是乘以3得到的,更新指针i3
if (dp[i] == next3)
i3++;
// 如果当前最小值是乘以5得到的,更新指针i5
if (dp[i] == next5)
i5++;
}
// 返回第N个丑数
return dp[N - 1];
}
详解代码
- 特殊处理:首先判断 N 是否小于等于 6,因为前 6 个丑数就是 [1, 2, 3, 4, 5, 6],直接返回即可。
- 初始化指针和数组:
i2
,i3
,i5
分别指向乘以 2、3、5 后可以得到的最小丑数索引。数组dp
用于存储从小到大生成的丑数,初始值为dp[0] = 1
。 - 计算最小值:每次循环中,分别计算
next2 = dp[i2] * 2
,next3 = dp[i3] * 3
,next5 = dp[i5] * 5
,然后取这三个值的最小值作为下一个丑数。 - 更新指针:如果当前生成的丑数是乘以 2 得到的,则指针
i2
向后移动,以便下次循环使用更新的丑数;如果是乘以 3 或 5 得到的,也分别移动指针i3
和i5
。
复杂度分析
- 时间复杂度:O(N),因为我们只需要生成 N 个丑数,每次生成一个丑数的操作时间是常数。
- 空间复杂度:O(N),因为我们使用了一个长度为 N 的数组来存储丑数。
😄总结
丑数问题通过动态规划的方式,巧妙地利用三个指针生成新的丑数,并且保证了每个丑数都是按顺序生成的。通过这种方式,我们可以在 O(N) 的时间内得到第 N 个丑数,是一种高效的解决方案。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)