法一:暴力求解
遍历所有可能的非负数的平方和。
class Solution {
public:
bool judgeSquareSum(int c) {
long long a, b;
int lim = sqrt(c) + 1;
for(a = 0; a < lim; a++) {
int sum = a * a; // 避免在第二层for循环中重复计算
for(b = 0; b < lim; b++) {
if(sum + b * b == c) return true;
}
}
return false;
}
};
法二:暴力求解优化
与167题思想类似,考虑进行问题的转化:
将“是否存在两个非负整数 a 和 b 使得 a * a + b * b = c ”转化为“是否存在非负整数 b 使得 b * b = c - a * a”
class Solution {
public:
bool judgeSquareSum(int c) {
long long a, b;
int lim = sqrt(c) + 1;
for(a = 0; a < lim; a++) {
b = (long long)(sqrt(c - a * a));
if(b == sqrt(c - a * a)) return true;
}
return false;
}
};
法三:
使用二分查找。
class Solution {
public:
// 二分查找:在[start, end]范围中查找是否存在整数mid使得 mid^2 = value
bool bSearch(int start, int end, int value) {
if (start > end)
return false;
int mid = start + (end - start) / 2;
if (mid * mid == value) {
return true;
} else if (mid * mid > value) {
return bSearch(start, mid - 1, value);
} else {
return bSearch(mid + 1, end, value);
}
}
bool judgeSquareSum(int c) {
long long a, b;
int lim = sqrt(c) + 1;
for (a = 0; a < lim; a++) {
b = c - a * a;
if (bSearch(0, b, b))
return true;
}
return false;
}
};
法四:双指针
同167题。平方和最小值为 0 * 0 = 0, 最大值为 (long)sqrt(c) 的平方。
class Solution {
public:
bool judgeSquareSum(int c) {
long a = 0, b = sqrt(c);
while(a <= b) {
if(a * a + b * b == c) return true;
else if(a * a + b * b < c) ++a;
else --b;
}
return false;
}
};
另外,还可以使用Fermat定理求解。