[路飞]_程序员必刷力扣题: 633. 平方数之和

231 阅读1分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

633. 平方数之和

力扣链接

给定一个非负整数 c ,你要判断是否存在两个整数 ab,使得 a2 + b2 = c

示例 1:

输入: c = 5
输出: true
解释: 1 * 1 + 2 * 2 = 5

示例 2:

输入: c = 3
输出: false

示例 3:

输入: c = 4
输出: true

示例 4:

输入: c = 2
输出: true

示例 5:

输入: c = 1
输出: true

提示:

  • 0 <= c <= 231 - 1

方法一:通过开根来求解

思路

在理解题目意思以后,我们可以得出a * a <= c 且b * b <= c 这里我们就需要从0开始循环,在 0<=a && a * a <= c 的范围之间,去寻找一个合适的值。 通过c - a * a 我们可以得到b * b的值,要求b 我们需要开平方。使用Math.sqrt来处理 得到的结果必须是一个整数,如果带有小数点则不是我们需要的 所以b === parseInt(b)如果满足条件则返回true,否则继续循环直到结束未找到则返回false

var judgeSquareSum = function (c) {
    for (let a = 0; a * a <= c; a++) {
        const b = Math.sqrt(c - a * a);
        if (b === parseInt(b)) {
            return true;
        }
    }
    return false;
}

方法二: 双指针

思路

另外一种思路就是通过双指针的方式:

我们声明两个数left和right满足left<=right,假设 total = left * left + right * right,如果c存在两个数的平方和相加等于c,那么total===c

接下来我们让left从0开始,right从Math.floor(Math.sqrt(c))开始(为什么想下去取整,如果向上的话就肯定导致total大于c了)

然后跟据total的结果,让指针逐步向中间靠拢,

  • 假设right在正确的值,那么left从0开始必然是偏小,需要left逐渐增大
  • 假设left在正确的位置,那么right从最大值开始必然是偏大,需要right逐渐减小

由上可得,如果total>c 那么我们就让right--

如果total<c 那么我们就让left++

一直循环,重复以上步骤,

  • 如果total===c:那么直接返回true
  • 如果当left===right的时候如果total还是!==c: 那就证明不存这样的left和right 在函数末尾返回false
/**
 * @param {number} c
 * @return {boolean}
 */
var judgeSquareSum = function (c) {
    var left = 0;
    var right = Math.floor(Math.sqrt(c))
    while(left<=right){
        var total = left*left+right*right
        if(total===c){
            return true
        }
        if(total>c){
            right--
        }
        if(total<c){
            left++
        }
    }
    return false
};