0313. 超级丑数
大约 3 分钟
---
0313. 超级丑数
- 标签:数组、数学、动态规划
- 难度:中等
题目链接
题目大意
描述:
「超级丑数」是一个正整数,并满足其所有质因数都出现在质数数组 中。
给定一个整数 和一个整数数组 。
要求:
返回第 个 超级丑数。
说明:
- 题目数据保证第 个「超级丑数」在 带符号整数范围内。
- 。
- 。
- 。
- 题目数据 保证 是一个质数。
- 中的所有值都「互不相同」,且按「递增顺序」排列。
示例:
- 示例 1:
输入:n = 12, primes = [2,7,13,19]
输出:32
解释:给定长度为 4 的质数数组 primes = [2,7,13,19],前 12 个超级丑数序列为:[1,2,4,7,8,13,14,16,19,26,28,32] 。- 示例 2:
输入:n = 1, primes = [2,3,5]
输出:1
解释:1 不含质因数,因此它的所有质因数都在质数数组 primes = [2,3,5] 中。解题思路
思路 1:动态规划 + 多指针
核心思想:超级丑数是只包含给定质数数组中质因数的正整数。我们可以使用动态规划的思想,维护一个数组 来存储前 个超级丑数,并使用多个指针来跟踪每个质数应该与哪个超级丑数相乘。
数学原理:
- 超级丑数序列:
- 每个超级丑数都可以表示为:,其中 遍历所有质数
- 当 时,将 加 1
算法步骤:
初始化:创建数组 存储超级丑数,。创建指针数组 ,初始化为全 0。
动态规划计算:对于 从 1 到 :
- 计算所有可能的候选值:
- 找到最小值:
- 更新指针:对于所有 ,如果 ,则
返回结果:返回 。
思路 1:代码
class Solution:
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
# dp[i] 表示第 i+1 个超级丑数
dp = [0] * n
dp[0] = 1 # 第一个超级丑数是 1
# pointers[j] 表示 primes[j] 应该与 dp[pointers[j]] 相乘
pointers = [0] * len(primes)
# 计算第 2 到第 n 个超级丑数
for i in range(1, n):
# 计算所有可能的候选值
candidates = [dp[pointers[j]] * primes[j] for j in range(len(primes))]
# 找到最小值作为下一个超级丑数
dp[i] = min(candidates)
# 更新指针:如果当前超级丑数等于某个候选值,则对应指针加 1
for j in range(len(primes)):
if dp[i] == dp[pointers[j]] * primes[j]:
pointers[j] += 1
return dp[n - 1]思路 1:复杂度分析
- 时间复杂度:,其中 是要求的超级丑数个数, 是质数数组的长度。对于每个超级丑数,我们需要遍历所有质数来计算候选值并更新指针。
- 空间复杂度:,其中 用于存储 数组, 用于存储 数组。