一、题意
给你一个整数 n ,返回 和为 n 的完全平方数的最少数量 。
完全平方数 是一个整数,其值等于另一个整数的平方;换句话说,其值等于一个整数自乘的积。例如,1、4、9 和 16 都是完全平方数,而 3 和 11 不是。
二、解法
解法一:
动态规划
求排列数
dp[i]代表和为i的最小完全平方数数量
dp[0]=0
dp[i]=min(dp[i],dp[i-j*j]+1)
时间复杂度:
O
(
n
×
n
)
O(n\times \sqrt n )
O(n×n)
空间复杂度:
O
(
n
)
O(n)
O(n)
解法二:
数学
四平方数和定理
四平方和定理证明了任意一个正整数都可以被表示为至多四个正整数的平方和。
同时四平方和定理包含了一个更强的结论:
1、
n
=
4
k
(
8
m
+
7
)
n= 4^k(8m+7)
n=4k(8m+7),数量为四
2、
n
≠
4
k
(
8
m
+
7
)
n\not=4^k(8m+7)
n=4k(8m+7),
答案为1,n为完全平方数
答案为2,
n
=
a
2
+
b
2
n=a^2+b^2
n=a2+b2,遍历1到
n
\sqrt n
n,判断
n
−
a
2
n-a^2
n−a2是否为完全平方数
答案为3,不符合上述情况即为该情况。
时间复杂度:
O
(
n
)
O(\sqrt n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
三、代码
解法:
int numSquares(int n) {
int m = (int)sqrt(n);
vector<int> dp(n+1,n);
dp[0]=0;
for(int i=1;i<=n;i++){
for(int j=1;j*j<=i;j++){
int v = i-j*j;
if(v>=0)
dp[i]=min(dp[i],dp[v]+1);
}
}
return dp[n];
}
四、总结
与leetcode 322. Coin Change 问题是同一个问题,只是硬币特殊了点,都是完全平方数。
五、引用
[1] leetcode:279. Perfect Squares
[2] leetcode:279. Perfect Squares官方解法