279. 完全平方数
难度中等916
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...
)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
给你一个整数 n
,返回和为 n
的完全平方数的 最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1
、4
、9
和 16
都是完全平方数,而 3
和 11
不是。
示例 1:
输入:n = 12
输出:3
解释:12 = 4 + 4 + 4
示例 2:
输入:n = 13
输出:2
解释:13 = 4 + 9
class Solution {
public:
int numSquares(int n) {
// 首先这是一个纯完全背包问题
/*
所以,我们不用取管先遍历背包还是先遍历物品,因为都可以
*/
/*
思路就是,先找出背包和物品;
背包就是n
物品就是符合条件的完全平方数
*/
// 第一步,先找出符合条件的完全平方数
vector<int> objects;
int k=1;
while(k*k<=n) {
// cout<<"k: "<<k<<" ";
objects.push_back(k*k);
k++;
// k=k*k;
}
if(objects.back()==n) {
return 1;
}
vector<int> dp(n+1,INT_MAX);
// for(auto a :objects) {
// cout<<a<<" ";
// }
// 初始化
dp[0]=0;
// 先遍历物品再遍历背包
for(int i=0;i<objects.size();i++) {
for(int j=objects[i];j<=n;j++) {
dp[j]=min(dp[j-objects[i]]+1,dp[j]);
}
}
// 先遍历背包再遍历物品
// for(int i=0;i<=n;i++) {
// for(int j=0;j<objects.size();j++) {
// if(i-objects[j]>=0) {
// dp[i]=min(dp[i-objects[j]]+1,dp[i]);
// }
// }
// }
return dp[n];
}
};
其实无论遍历谁dp的含义都没有改变,读者也可以验证问题的无后效形和最优子结构
为什么dp初始化的时候是INT_MAX
因为你会发现,举例dp[1]=min(dp[1-1]+1,dp[1]); dp[2]=min(dp[2-1]+1,dp[2]); 所以只要初始化dp[0]=0就可以