279. 完全平方数
1.题目描述
给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, …)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。
示例 1:
示例 2:
2.思路(动态规划)
假设最小完全平方的个数
ƒ
(
n
)
=
m
ƒ(n) = m
ƒ(n)=m,那么
n
n
n的值满足下列公式
∑
(
A
[
i
]
∗
A
[
i
]
)
=
n
∑(A[i] * A[i]) = n
∑(A[i]∗A[i])=n
令
k
k
k 为满足最小值
m
m
m 的时候,最大的平方数 。 令
d
+
k
∗
k
=
n
;
d
>
=
0
d + k*k = n ; d >= 0
d+k∗k=n;d>=0。( 注意:一定要是满足m最小的时候的
k
k
k值)
得出
f
(
d
)
+
f
(
k
∗
k
)
=
f
(
n
)
f(d) + f(k*k) = f(n)
f(d)+f(k∗k)=f(n) 显然
f
(
k
∗
k
)
=
1
f(k * k) = 1
f(k∗k)=1; 则
f
(
d
)
+
1
=
f
(
n
)
f(d) + 1 = f(n)
f(d)+1=f(n); 因为
d
=
n
−
k
∗
k
d = n - k*k
d=n−k∗k
则可以推出
ƒ
(
n
−
k
∗
k
)
+
1
=
ƒ
(
n
)
ƒ(n - k * k) + 1 = ƒ(n)
ƒ(n−k∗k)+1=ƒ(n) ; 且
k
∗
k
<
=
n
k * k <= n
k∗k<=n,所以动态转移方程:
d
p
[
i
]
=
m
i
n
(
d
p
[
i
]
,
d
p
[
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)