[路飞]超级丑数

121 阅读1分钟

题目描述

超级丑数 是一个正整数,并满足其所有质因数都出现在质数数组 primes 中。

给你一个整数 n 和一个整数数组 primes ,返回第 n 个 超级丑数 。

题目数据保证第 n 个 超级丑数 在 32-bit 带符号整数范围内。

解题思路

算法

动态规划,dp[i] 是第 i 个丑数

过程

对于每一个丑数,都是由另一个丑数(从 1 开始)乘上给的因子得来的(prime[i]),因此我们要做的,就是从小到大把丑数列出来放到 dp,然后返回 dp[n - 1] 即可

在计算过程中,我们用一个数组,作为每个与因数相乘的丑数的 index,因为每个丑数都只和因数有一个相乘机会。 在用一个数组来存放已经计算好的丑数

另外在计算过程中,我们要注意的一点是,在得到一个丑数的时候,如果发现已经计算过的丑数值里,已经有了相同的丑数(这个丑数肯定还没放入 dp),那么我们要将所有相等于本轮最小值丑数的因子,他对应的 index 进行 ++ 操作,然后再算出一个新的丑数出来,这是我们去重的关键

代码

/**
 * @param {number} n
 * @param {number[]} primes
 * @return {number}
 */
var nthSuperUglyNumber = function (n, primes) {
  const dp = new Array(n + 1).fill(0)
  const m = primes.length
  const pointers = new Array(m).fill(0)
  const nums = new Array(m).fill(1)
  for (let i = 1; i <= n; i++) {
    let minNum = Number.MAX_SAFE_INTEGER
    for (let j = 0; j < m; j++) {
      minNum = Math.min(minNum, nums[j])
    }
    dp[i] = minNum
    for (let j = 0; j < m; j++) {
      if (nums[j] == minNum) {
        pointers[j]++
        nums[j] = dp[pointers[j]] * primes[j]
      }
    }
  }
  return dp[n]
}