Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, ...) which sum to n.
For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.
输入一个正整数,将其表示成完全平方数的和,求最少需要的完全平方数的个数。
法一:一个正整数能表示成若干个完全平方数的和,记为x=c12+c22+...+cn2,记c12+c22+...+cn-12=a,则x=a+cn2,其中0=<a<=x。因此,表示成x的平方数的最少个数,即为表示成a的平方数的最少个数加1。一直递推下去,即可求出。其实,就是一个动态规划问题。
代码如下:
int numSquares(int n)
{
vector<int> dp(n + 1, INT_MAX);
for (int i = 0; i*i <= n; i++)
dp[i*i] = 1;
for (int i = 0; i <= n; i++)
{
for (int j = 0; i + j*j <= n; j++)
dp[i + j*j] = (dp[i] + 1) > (dp[i + j*j]) ? (dp[i + j*j]) : (dp[i] + 1);
}
return dp[n];
}
法二:(此方法参考于此,感谢网友分享!)由四平方和定理可知,任何一个正整数都可表示为4个以内完全平方数的和。
此外,由归纳法得出
- 一个数如果含有4这个因子,去掉这个因子并不影响结果;
- 一个数若对8求余结果为7的话,这个数必定由4个完全平方数组成。
最终代码如下:
int numSquares(int n)
{
while (n % 4 == 0) n /= 4;
if (n % 8 == 7) return 4;
for (int i = 0; i*i <= n; i++)
{
int j = sqrt(n - i*i);
if (j*j + i*i == n)
return !!i + !!j;
}
return 3;
}
ps:若在法一加上法二归纳法所得结论,可极大提高运算效率!
浙公网安备 33010602011771号