279. Perfect Squares [JavaScript]

一、解题思路

  这是一道典型的动态规划题目(不要求求解具体的方案)。

  定义状态:

  dp[i]表示完全平方数组成i最少的个数

  边界情况:

  dp[i] = 1

  状态转移方程:

  if k * k = i 
    dp[i] = 1
  else
    dp[i] = Math.min(dp[i], dp[i - j] + dp[j])

  由于在dp[i - j] + dp[j]中产生大量重复运算,只需要计算i/2即可:

const numSquares = n => {
  const dp = new Array(n + 1).fill(Number.MAX_SAFE_INTEGER)
  dp[1] = 1
  for (let i = 2; i <= n; i++) {
    const s = Math.floor(Math.sqrt(i))
    for (let j = i - 1; j >= Math.floor(i / 2); j--) {
      if (Math.pow(s, 2) === i) {
        dp[i] = 1
      }
      dp[i] = Math.min(dp[j] + dp[i - j], dp[i])
    }
  }
  return dp[n]
}

  再来思考一下上述状态转移方程,你会发现当一个数不是完全平方数时,必须去找一个能组成其和的最大完全平方数,才能确保其个数最少,那么实际上状态转移方程又可以优化为:

  if k * k = i
    dp[i] = 1
  else
    dp[i + j * j] = Math.min(dp[i + j * j], dp[i] + 1)

二、代码实现

const numSquares = n => {
  const dp = new Array(n + 1).fill(Number.MAX_SAFE_INTEGER)

  for (let i = 1; i * i <= n; i++) {
    dp[i * i] = 1
  }

  for (let i = 1; i < n; i++) {
    for (let j = 1; i + j * j <= n; j++) {
      dp[i + j * j] = Math.min(dp[i] + 1, dp[i + j * j])
    }
  }

  return dp[n]
}

  
  ----------------------------

关注「漫谈大前端」
不断成长为一名优秀的前端开发工程师

  ----------------------------
  

  您还可以在这些地方找到我:

猜你喜欢

转载自blog.csdn.net/dai_qingyun/article/details/88320927