题目描述
原题链接:279. 完全平方数
解题思路
(1)二维数组
- 动态规划五步曲:
(1)dp[i][j]: 在和为j的前提下,从1-i中选出对应的完全平方数,用最少的数组合出j,所使用的数的个数。
(2)递推公式: dp[i][j] = min(dp[i - 1][j], dp[i][j - i * i] + 1),完全背包的一般公式,dp[i][j - i * i] + 1
:使用这个数的完全平方的情况加上一。
(3)dp数组初始化: 因为求的是MIN,就要求都初始化为INT_MAX,再让dp[i][0] = 0,便于计算。
(4)遍历顺序: 因为最后求的是唯一的最小值,不需考虑顺序问题,先背包再物品,先物品再背包都可以,内层从小到大。
(5)举例: (省略)
class Solution {
public:
int numSquares(int n) {
vector<vector<int>> dp(n + 1, vector<int>(n + 1, INT_MAX));
for(int i = 0; i <= n; i++) dp[i][0] = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(j < i* i) dp[i][j] = dp[i - 1][j];
else dp[i][j] = min(dp[i - 1][j], dp[i][j - i * i] + 1);
}
}
return dp[n][n];
}
};
此方式,在两三个用例中会超时。
(2)一维滚动数组
递推公式写为二维的等价式dp[j] = min(dp[j], dp[j - i * i] + 1)
,初始化dp[0]=0
。
举例
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n + 1, INT_MAX);
dp[0] = 0;
for(int i = 1; i <= n; i++) {
for(int j = i * i; j <= n; j++) {
dp[j] = min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
}
};