i-jj就是x
https://leetcode-cn.com/problems/perfect-squares/solution/chao-zhi-bai-kao-zui-jiang-xiao-xue-sheng-du-neng-/
又是dp,最少(最多)=最优解就要想到dp。
此处dp[i]可能由dp[0]到dp[i-1]推出,因为i一定等于x+jj,那么dp[i]就是dp[x]+1,开一个大小为n+1的dp数组(为啥n+1自己想),dp[0]就等于0,从1遍历到n,在里面找i的最优解,j从1开始遍历,退出条件是i-jj<0,那么dp[i]就等于dp[i]和dp[i-jj]+1中比较小的那个。所以我们一开始要将dp数组赋为无穷大
class Solution {
public:
int numSquares(int n) {
// 1,对于正整数N, 所有的解都是 N = 一个整数的平方 + 另一个整数; 直白点, N = AxA + B
// 2, 而B又是由 "一个整数的平方 + 另一个整数" 组成的; 那么, B = CxC + D
// 3,总结下就是:N = IxI + N' 而 N' = IxI + N''
//dp[i]存的是组成数字i需要几个完全平方数,dp[i]就等于dp[x]+1
//x就是0到i-1中,x+?*?=i,?*?是一个平方数,证明x到i只需要加上一个完全平方数即可
//dp[x]又要是dp[1]到dp[i-1]最小的
//dp[13] = dp[4]+1
//dp[12] = dp[8]+1
vector<int> dp(n+1,INT_MAX);
dp[0] = 0;
for(int i = 1; i <= n; ++i){
//j就是上面说的?,i-j*j就是上面的x
//dp[4],j=1,证明x是3,dp[3]等于3
//dp[4],j=2,证明x是0,dp[0]等于0
for(int j = 1; i - j * j >= 0; ++j){
dp[i] = min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
};
class Solution {
public:
//参数有n,nums也就是用的数字的数量,index,当前用到的完全平方数是几,接下来用的只能小于等于当前这个
// void dfs(int n, int nums, int index){
// if(n == 0){
// res = min(nums,res);
// return;
// }
// else if(nums < 0) return;
// for(int i = index; i >= 1; --i){
// dfs(n-i*i,nums+1,i);
// }
// }
int numSquares(int n) {
//个数最少,那么用的完全平方数就要尽可能的大
//感觉有点dp的味道,不是dp就是dfs爆搜,把所有情况搜出来,比较用的元素最少的
//爆搜要超时,dp或者记忆化
// for(int i = (int)sqrt(n); i >= 1; --i){
// dfs(n-i*i,1,i);
// }
// return res;
vector<int> dp(n+1,INT_MAX);
//从前往后填表
dp[0]=0;//初始化dp数组最重要!
for(int i = 1; i <= n; ++i){
//比如dp[12]就可以推出dp[8]+1或者dp[11]+1,12和8和11中间差了就是一个完全平方数,所以只要推出前面的,就能计算出dp[12]的结果,因为就几种情况,dp[11]+1,dp[8]+1,dp[3]+1
for(int j = 1; i -j*j >= 0; ++j){
dp[i] = min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
// private:
// int res = INT_MAX;
};
三刷了,这次真的轻松做出了。dp[i]的含义是最少可以用dp[i]个完全平方数加起来等于i
class Solution {
public:
int numSquares(int n) {
//dp的题,dp[i]的含义是可以用dp[i]个完全平方数加起来等于i
//所以状态转移方程是dp[i] = min(dp[i],dp[i-j*j]+1)
//从小到大进行填表,初始化为dp[0]=0
vector<int> dp(n+1,INT_MAX);
dp[0] = 0;
for(int i = 1; i <= n; ++i){
for(int j = 1; i - j*j >= 0; ++j){
dp[i] = min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
};
四刷
class Solution {
public:
int numSquares(int n) {
//dp[i]记录的是组成i最少需要几个完全平方数
//dp[i] = min(dp[i-j*j]+1,dp[i]),因为i一定可以从j*j到i,i-j*j可以通过dp[i-j*j]个数字组成,j*j又一定是一个完全平方数
//初始化:dp[0]=0,当组成0的时候需要0个完全平方数即可
vector<int> dp(n+1,INT_MAX);
dp[0] = 0;
for(int i = 1; i <= n ;++i){
//所以一直从j=1遍历到i-j*j<0为止,等于0也要包括进去
for(int j = 1; i-j*j>=0; ++j){
dp[i] = min(dp[i-j*j]+1,dp[i]);
}
}
return dp[n];
}
};