【动态规划】LeetCode 279 完全平方数-Medium

269 阅读1分钟

题目

给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

示例 1:

输入: n = 12
输出: 3 
解释: 12 = 4 + 4 + 4.

示例 2:

输入: n = 13
输出: 2
解释: 13 = 4 + 9.

动态规划四步走

1. 定义状态
2. 初始状态
3. 状态转移方程
4. 从dp[]中获取结果

具体到题目

定义状态

定义dp[i]为数字i的最小完全平方和的个数

初始状态

dp[0] = 1 ; dp[1] = 1

状态转移方程

定义变量k=1;对于数字i,如果 k+1是完全平方数,且k+1的平方为i,则dp[i] = 1 ,k自增;

否则,遍历1到k,dp[i] = 1+ dp[i-j * j]的最小值

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

完整代码

// @lc code=start
/**
 * @param {number} n
 * @return {number}
 */
var numSquares = function (n) {
  if (n <= 0) {
    return;
  }
  const dp = [];
  dp[0] = 1;
  dp[1] = 1;
  let k = 1;
  for (let i = 2; i <= n; i++) {
    if ((k + 1) * (k + 1) === i) {
      dp[i] = 1;
      k++;
      continue;
    }
    let min = i;
    for (let j = 1; j <= k; j++) {
      min = Math.min(min, 1 + dp[i - j * j]);
    }
    dp[i] = min;
  }
  console.log(dp);
  return dp[n];
};

总结

题目还算比较简单,第一次的时候感觉只需要比较k和k-1即可,知道碰到48,此时k为6,而最优解为48=16+16+16,因此改为遍历1到k,感觉其中还可以优化,不需要遍历这么多。