给定一个非负整数 c
,你要判断是否存在两个整数 a
和 b
,使得 a2 + b2 = c
。
解析:
求的正整数的平方数之和等于某个树,那么 a 和 b 必然 < c,最先想到的通用求解方法即遍历小于 c 的所有数字,然后分别取平方,再相加,判断是否相等。
采用双指针的方法:分别从0和最大值去进行取平方相加:
设左指针为 left,右指针为 right。 sum = left * left + right * right 则有:
-
left 始终 <= right
-
sum = c ,则 return true
-
sum < c , 则 left++ (如果移动右指针那么 sum 将会更小)
-
sum > c, 则 right-- (如果移动左指针,那么 sum 将会更大)
图解:
代码:
var judgeSquareSum = function(c) {
let left = 0
let right = c
while(left <= right) {
const leftNumer = left * left
const rightNumber = right * right
const sum = leftNumer + rightNumber
if (sum === c) {
return true
} else if (sum > c) {
right--
} else {
left++
}
if (leftNumer > c) {
return false
}
}
return false
};
这样可以求得正解,代码量也不多,但是不能发现有个非常大的缺点,就是不必要的遍历和计算太多,极大的浪费内存。譬如:c = 13 时, 右指针第一个取 12 * 12,这样的计算实际上是没有必要的。第一个右指针应当是小于C的第一个平方数。c = 13 时,第一个右指针应当指向 3*3 = 9.左指针 0,那么只需要很少的计算就能够求的是否满足条件了。
右侧指针的初始位置应当为 Math.floor(Math.sqrt(c))
可以将计算按照以下优化:
let right = Math.floor(Math.sqrt(c))
完整代码:
/**
* @param {number} c
* @return {boolean}
*/
var judgeSquareSum = function(c) {
let left = 0
let right = Math.floor(Math.sqrt(c))
while(left <= right) {
const leftNumer = left * left
const rightNumber = right * right
const sum = leftNumer + rightNumber
if (sum === c) {
return true
} else if (sum > c) {
right--
} else {
left++
}
if (leftNumer > c) {
return false
}
}
return false
};