【leedcode】313. 超级丑数

133 阅读1分钟

这是我参与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]