bigpotato

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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个以内完全平方数的和。

此外,由归纳法得出

  1. 一个数如果含有4这个因子,去掉这个因子并不影响结果;
  2. 一个数若对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:若在法一加上法二归纳法所得结论,可极大提高运算效率!

posted on 2018-03-19 15:58  bigpotato  阅读(124)  评论(0)    收藏  举报