这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战
难度:中等
题目简介
超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 primes 中。
给你一个整数 n 和一个整数数组 primes ,返回第 n 个 超级丑数 。
题目数据保证第 n 个 超级丑数 在 32-bit 带符号整数范围内。
示例 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 <= n <= 106 1 <= primes.length <= 100 2 <= primes[i] <= 1000 题目数据 保证 primes[i] 是一个质数 primes 中的所有值都 互不相同 ,且按 递增顺序 排列
解题思路
最小堆
没有很好地利用给定的primes是递增的这一条件,很暴力地利用最小堆找第n个。 动态规划:
class Solution:
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
pd = [1]
count = 1
seend = {1}
while count < n:
cur = heapq.heappop(pd)
count += 1
for p in primes:
if cur * p not in seend:
seend.add(cur * p)
heapq.heappush(pd, cur * p)
return pq[0]
动态规划
- 首先判断 primes 是递增的,
- 每个质因子要生成新的丑数的时候,我们要对比的是谁生成的更小比如[2,3,5]中,一开始是12,13,1*51∗2,1∗3,1∗5
- 新的就要在 22, 13, 1*52∗2,1∗3,1∗5之间选一个。
- 以此类推,只要更新每个质因子对应的丑数坐标即可。
class Solution:
def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
m = len(primes)
dp = [inf] * n
dp[0] = 1
indexes = [0] * m
for i in range(1, n):
changeIndex = 0
for j in range(m):
# 如果当前质因子乘它的丑数小于当前的丑数,更新当前丑数并更新变化坐标
if primes[j] * dp[indexes[j]] < dp[i]:
changeIndex = j
dp[i] = primes[j] * dp[indexes[j]]
elif primes[j] * dp[indexes[j]] == dp[i]:
indexes[j] += 1
# 变化的坐标+1
indexes[changeIndex] += 1
return dp[-1]