题目链接:
给你一个整数 n
,返回 和为 n
的完全平方数的最少数量 。
完全平方数
示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9
提示:
-
1 <= n <= 104
解题思路
在这道题中,可以将完全平方数看成是物品(无限个),求装满背包容量为n的最少有多少物品。这就和
运用动态规划五部曲解决问题:
-
确定dp数组以及其下标的含义
dp[j]
表示凑成数为j所需的最少完全平方数数量 -
确定递推公式
dp[j] = min(dp[j], dp[j - i * i]] + 1)
-
dp数组的初始化
dp[0]
表示 和为0的完全平方数的最小数量,dp[0] = 0
根据递推公式求最小值,下标非0的
dp[j]
初始化为一个最大的数,否则在比较(dp[j], dp[j - i * i]] + 1)
的过程中被初始值覆盖掉。 -
确定遍历顺序
本题求解的是完全平方数的最小数量,也就是求数量,与顺序没有关系,所以先遍历物品还是先遍历背包都可以。
-
举例推导dp数组(略)
C++
class Solution { public: int numSquares(int n) { vector<int> dp(n + 1, INT_MAX); dp[0] = 0; for (int i = 1; i * i < n; i++) { for (int j = i * i; j < n + 1; j++) { if (dp[j - i * i] != INT_MAX) { dp[j] = min(dp[j], dp[j - i * i] + 1); } } } return dp[n]; } };
JavaScript
/** * @param {number} n * @return {number} */ var numSquares = function(n) { const dp = new Array(n + 1).fill(Number.MAX_VALUE); dp[0] = 0; for (let j = 0; j <= n; j++) { for (let i = 1; i * i <= n; i++) { if (j >= i * i && dp[j - i * i] != Number.MAX_VALUE) { dp[j] = Math.min(dp[j], dp[j - i * i] + 1); } } } return dp[n]; };