Given a non-negative integer c
, your task is to decide whether there're two integers a
and b
such that a2 + b2 = c.
Example 1:
Input: 5 Output: True Explanation: 1 * 1 + 2 * 2 = 5
Example 2:
Input: 3 Output: False
Approach #1 Brute Force [Time Limit Exceeded]
bool judgeSquareSum(int c) {
int i,j;
for(i=0;i*i<=c;i++)
for(j=0;j*j<=c;j++)
{
if(i*i+j*j==c)
return true;
}
return false;
}
此方法虽然简单,但是给定一个比较大的数时,往往在指定时间内求不出结果。
Approach #2 Better Brute Force [Time Limit Exceeded]
We can improve the last solution, if we make the following observation. For any particular aaa chosen, the value of bbb required to satisfy the equation a2+b2=ca^2 + b^2 = ca2+b2=c will be such that b2=c−a2b^2 = c - a^2b2=c−a2. Thus, we need to traverse over the range (0,c)(0, \sqrt{c})(0,√c) only for considering the various values of aaa. For every current value of aaa chosen, we can determine the corresponding b2b^2b2 value and check if it is a perfect square or not. If it happens to be a perfect square, ccc is a sum of squares of two integers, otherwise not.
Now, to determine, if the number c−a2c - a^2c−a2 is a perfect square or not, we can make use of the following theorem: "The square of nthn^{th}nth positive integer can be represented as a sum of first nnn odd positive integers." Or in mathematical terms:
n2=1+3+5+...+(2∗n−1)=∑1n(2∗i−1)n^2 = 1 + 3 + 5 + ... + (2*n-1) = \sum_{1}^{n} (2*i - 1)n2=1+3+5+...+(2∗n−1)=∑1n(2∗i−1).
To look at the proof of this statement, look at the L.H.S. of the above statement.
1+3+5+...+(2∗n−1)=1 + 3 + 5 + ... + (2*n-1)=1+3+5+...+(2∗n−1)=
(2∗1−1)+(2∗2−1)+(2∗3−1)+...+(2∗n−1)=(2*1-1) + (2*2-1) + (2*3-1) + ... + (2*n-1)=(2∗1−1)+(2∗2−1)+(2∗3−1)+...+(2∗n−1)=
2∗(1+2+3+....+n)−(1+1+...ntimes)=2*(1+2+3+....+n) - (1+1+...n times)=2∗(1+2+3+....+n)−(1+1+...ntimes)=
2∗n∗(n+1)/2−n=2*n*(n+1)/2 - n=2∗n∗(n+1)/2−n=
n∗(n+1)−n=n*(n+1) - n=n∗(n+1)−n=
n2+n−n=n2n^2 + n - n = n^2n2+n−n=n2
根据以上原理,第一次写出的代码总是运行错误,后来才发现一行代码的位置放错导致逻辑出错。
bool judgeSquareSum(int c) {
int i,b;
// int j=1,sum=0; 该行代码应该放在循环内部,否则对每一个i,j和sum的值将一直增加,
for(i=0;i*i<=c;i++)
{
b=c-i*i;
int j=1,sum=0;
while(sum<b)
{
sum=sum+j;
j+=2;
}
if(sum==b)
return true;
}
return false;
}
但还是运行时间过长。
Approach #3 Using sqrt function[Time Limit Exceeded]
Algorithm
Instead of finding if c−a2c - a^2c−a2 is a perfect square using sum of odd numbers, as done in the last approach, we can make use of the inbuilt sqrtsqrtsqrt function and check if c−a2\sqrt{c - a^2}√c−a2 turns out to be an integer. If it happens for any value of aaa in the range [0,c][0, \sqrt{c}][0,√c], we can return a True value immediately.
bool judgeSquareSum(int c) {
int i;
double b;
for(i=0;i*i<=c;i++)
{
b=sqrt(c-i*i);
if(b==(int)b)
return true;
}
return false;
}
还是时间太长。
最后的代码如下:
bool judgeSquareSum(int c) {
int left=0,right=(int)sqrt(c);
while(left<=right)
{
int res=left*left+right*right;
if(res<c)
left++;
else if(res>c)
right--;
else
return true;
}
return false;
}