返回

高效算法解题:动态规划巧取丑数II

前端

在计算机科学领域,丑数被定义为仅由质因数2、3和5组成的正整数。例如,1、2、3、4、5、6、8、9、10都是丑数。

LeetCode 264题要求我们编写一个程序,找出第 n 个丑数。例如,当n=10时,第10个丑数是12。

为了解决这个问题,我们可以使用动态规划算法。动态规划是一种自底向上的解题方法,它将问题分解为更小的子问题,然后逐步解决这些子问题,最终得到问题的整体解决方案。

在LeetCode 264题中,我们可以将丑数序列表示为一个数组。数组的第一个元素是1,然后依次是2、3、4、5、6,依此类推。

为了找到第n个丑数,我们可以使用动态规划算法来填充这个数组。具体步骤如下:

  1. 初始化数组丑数数组dp,其中dp[0] = 1。
  2. 创建三个指针i2、i3和i5,分别指向dp数组中2、3和5的倍数的索引。
  3. 遍历dp数组,从索引1开始,直到索引n。
  4. 在每次迭代中,比较dp[i2]、dp[i3]和dp[i5]的大小,并选择其中最小的一个。将这个最小值存储在dp[i]中。
  5. 如果最小值是dp[i2],则将i2增加1,表示下一个2的倍数的索引。
  6. 如果最小值是dp[i3],则将i3增加1,表示下一个3的倍数的索引。
  7. 如果最小值是dp[i5],则将i5增加1,表示下一个5的倍数的索引。

重复步骤3到7,直到填充完dp数组。此时,dp[n]就是第n个丑数。

这里有一个使用JavaScript编写的LeetCode 264题的解决方案:

const uglyNumbers = (n) => {
  if (n <= 0) {
    throw new Error("Invalid input: n must be a positive integer.");
  }

  const dp = [1];
  let i2 = 0;
  let i3 = 0;
  let i5 = 0;

  for (let i = 1; i < n; i++) {
    const next2 = dp[i2] * 2;
    const next3 = dp[i3] * 3;
    const next5 = dp[i5] * 5;

    const nextUgly = Math.min(next2, next3, next5);

    dp.push(nextUgly);

    if (nextUgly === next2) {
      i2++;
    }

    if (nextUgly === next3) {
      i3++;
    }

    if (nextUgly === next5) {
      i5++;
    }
  }

  return dp[n - 1];
};

console.log(uglyNumbers(10)); // 12

这个解决方案的时间复杂度为O(n),空间复杂度为O(n)。

希望本文能帮助您理解LeetCode 264题的解题方法。如果您有任何问题,请随时留言。