leetcode 279. 完全平方数 -- javascript dp

·  阅读 789

279. 完全平方数

题目描述

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

给你一个整数 n ,返回和为 n 的完全平方数的 最少数量 。

完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。

image.png

题解

动态规划(Dynamic Programming, DP)

  • 动态规划只能应用于有最优 子结构的问题。最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似)。

  • 简单地说,问题能够分解成子问题来解决

  • 通俗一点来讲,动态规划和其它遍历算法(如深/广度优先搜索)都是将原问题拆成多个子问题然后求解,他们之间最本质的区别是,动态规划保存子问题的解,避免重复计算

  • 解决动态规划问题的关键是找到状态转移方程,这样我们可以通计算和储存子问题的解来求解最终问题

  • 同时,我们也可以对动态规划进行空间压缩,起到节省空间消耗的效果。

  • 在一些情况下,动态规划可以看成是带有状态记录(memoization)的优先搜索

  • 动态规划是自下而上的,即先解决子问题,再解决父问题;

  • 而用带有状态记录的优先搜索自上而下的,即从父问题搜索到子问题,若重复搜索到同一个子问题则进行状态记录,防止重复计算。

  • 如果题目需求的是最终状态,那么使用动态搜索比较方便;

  • 如果题目需要输出所有的路径,那么使用带有状态记录的优先搜索会比较方便。

回到本题目

我们定义一个一维矩阵 dp,其中 dp[i] 表示数字 i 最少可以由几个完全平方数相加构成。
枚举到k的时候,看k^2 算一个数dp[i] = 1, 加上剩下的i-k^2 计算还有多少的平方数 并且 包含的数目要求最小。

因此 dp[i] 可以取的最小值即为 1 + min(dp[i-1], dp[i-4], dp[i-9]...);

状态转移方程

image.png
因为计算 f[i] 时所需要用到的状态仅有 f[i-j^2] ,必然小于i,因此我们只需要从小到大地枚举 i 来计算 f[i]即可。

coding

/**
 * @param {number} n
 * @return {number}
 */
var numSquares = function(n) {
    let dp = new Array(n+1).fill(0);
    for(let i = 1; i <= n; i ++) {
        dp[i] = Number.MAX_SAFE_INTEGER;
        for(let j = 1; j*j <= i; j++) {
            dp[i] = Math.min(dp[i], dp[i- j*j] + 1);
        }
    }
    return dp[n];
};
复制代码
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改