题目描述
给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c。
示例1:
输入: 5
输出: True
解释: 1 * 1 + 2 * 2 = 5
示例2:
输入: 3
输出: False
分析
本题与167两数之和II非常类似,167的target是求和,这题的target是平方和。采用双指针的思想,一个指针low指向值较小的元素,一个指针high指向值较大的元素,移动指针直到找到两数平方和等于target。
本题需要注意的是high指针的初始化。low初始化为0即可,目的是要使low、high两指针指向的元素平方和趋近于target,故high初始化为sqrt(target)可降低时间复杂度。
算法思路:
- 如果两指针指向的元素平方和sum == target,找到唯一解,算法结束
- 如果sum < target,移动指向值较小元素的指针
- 如果sum > target,移动指向值较大元素的指针
时间复杂度:最多要遍历sqrt(target)个元素,O(sqrt(target))
空间复杂度:只使用了两个指针,O(1)
代码
public boolean judgeSquareSum(int c) {
//c为非负整数
if(c < 0)
return false;
int low = 0;
int high = (int)Math.sqrt(c);
while(low <= high) {
int tar = low*low + high*high;
if(tar == c) {
return true;
}
else if(tar < c) {
low++;
}
else {
high--;
}
}
return false;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int target = sc.nextInt();
SumOfSquareNumbers obj = new SumOfSquareNumbers();
System.out.println(obj.judgeSquareSum(target));
}
运行结果
提交修改记录
- 第一次提交答案错误,错误用例是input:2,output:false,expect:true,分析这个用例可以得出1 * 1 + 1 * 1 = 2,忽略了low和high指向同一个元素的情况,修改while的循环条件,将low < high改为low <= high,提交通过。
- 看到答案上有判断c是否为负数,根据题目要求,若为负数,返回false。加上这个判断条件之后执行时间缩短了。若不加,则tar恒大于c,high指针要遍历所有的元素之后才返回false,浪费时间。