本题也是完全背包问题。并且本质上与第322题一模一样。要求的是装满背包最少需要多少个物品。与第322题一样,dp数组的初始化需要仔细考虑。详见leetcode 322. Coin Change
本题,给定整数n就相当于给定容量大小为n的背包。n只可能等于,1,4,9,...,这些完全平方数的和。相当于物品个数就是
,物品重量是1,4,9,...,
。
第一版代码
外层循环遍历物品,内层循环遍历背包容量。
cpp
class Solution {
public:
int numSquares(int n) {
int m = sqrt(n);
//dp[j]表示和为j的完全平方数的最少数量
vector<int> dp(n+1,n+1);
//从题意可以看出,虽然0等于0的平方,但是本题完全平方数不包含0
//dp[0]初始化为0表示,无法找到和为0的完全平方数
dp[0] = 0;
for(int i = 1;i <=m;i++){//外层循环对物品遍历
for(int j = i*i;j <=n;j++){//内层循环对背包容量遍历
dp[j] = min(dp[j],dp[j-i*i]+1);
}
}
return dp[n];
}
};
第二版代码
外层循环遍历背包容量,内层循环遍历物品。
cpp
class Solution {
public:
int numSquares(int n) {
int m = sqrt(n);
//dp[j]表示和为j的完全平方数的最少数量
vector<int> dp(n+1,n+1);
//从题意可以看出,虽然0等于0的平方,但是本题完全平方数不包含0
//dp[0]初始化为0表示,无法找到和为0的完全平方数
dp[0] = 0;
// for(int i = 1;i <=m;i++){//外层循环对物品遍历
// for(int j = i*i;j <=n;j++){//内层循环对背包容量遍历
// dp[j] = min(dp[j],dp[j-i*i]+1);
// }
// }
for(int j = 0;j<=n;j++){//外层循环对背包容量遍历
for(int i = 1;i<=m;i++){//内层循环对物品遍历
if(j>=i*i)
dp[j] = min(dp[j],dp[j-i*i]+1);
}
}
return dp[n];
}
};