279. 完全平方数
1.题目描述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
示例 2:
2.思路(动态规划)
假设最小完全平方的个数ƒ(n)=mƒ(n) = mƒ(n)=m,那么nnn的值满足下列公式 ∑(A[i]∗A[i])=n∑(A[i] * A[i]) = n∑(A[i]∗A[i])=n
令 kkk 为满足最小值 mmm 的时候,最大的平方数 。 令 d+k∗k=n;d>=0d + k*k = n ; d >= 0d+k∗k=n;d>=0。( 注意:一定要是满足m最小的时候的kkk值)
得出 f(d)+f(k∗k)=f(n)f(d) + f(k*k) = f(n)f(d)+f(k∗k)=f(n) 显然f(k∗k)=1f(k * k) = 1f(k∗k)=1; 则 f(d)+1=f(n)f(d) + 1 = f(n)f(d)+1=f(n); 因为d=n−k∗kd = n - k*kd=n−k∗k
则可以推出ƒ(n−k∗k)+1=ƒ(n)ƒ(n - k * k) + 1 = ƒ(n)ƒ(n−k∗k)+1=ƒ(n) ; 且 k∗k<=nk * k <= nk∗k<=n,所以动态转移方程:
dp[i]=min(dp[i],dp[i−j∗j]+1)dp[i] = min(dp[i], dp[i - j * j] + 1)dp[i]=min(dp[i],dp[i−j∗j]+1)
3.代码
class Solution {
public:
int numSquares(int n) {
vector<int> dp(n+1);
for(int i = 1;i <= n;++i){
dp[i] = i;//最多的情况是分解为全1
for(int j = 1; i - j*j >= 0;++j){
dp[i] = min(dp[i],dp[i-j*j]+1);
}
}
return dp[n];
}
};
4.复杂度分析
时间复杂度:O(n*sqrt(n)),sqrt为平方根
空间复杂度:O(n)