[路飞]_leetcode-633-平方数之和

345 阅读2分钟

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

[题目地址] [B站地址]

给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 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

通过分析题意可知,c 为大于等于 0 的整数,ab 也是大于等于 0 的整数。

那我们想一个问题,就是如果 c 开平方之后的结果 n 是一个整数,是不是就说明 c=n²+0²

如果 n 不是整数,那么就说明 0 也不可能是 ab中的一个,那么我们接下来可以去哪里继续查找可能的值呢?

只能是大于 0 且 小于等于 n 的整数,然后我们固定一个数,求得另一个数的平方和为 c-a²,再将这个结果开方,如果开方后的结果是一个整数,则说明这两个数的平方和为 c,返回 true 即可,反之继续查找

知道在上述区间中没有找到满足条件的组合,返回 false

至此,本题的解题思路就完成了,代码如下:

var judgeSquareSum = function(c) {
    let max = Math.sqrt(c);
    if(isInteger(max)) return true;
    // 依次判断大于0的整数是否是满足条件的一个整数
    for(let i = 1;i<max;i++){
        const target = Math.sqrt(c-Math.pow(i,2))
        if(isInteger(target)) return true;
    }
    return false;
    // 判断传入数值是否是整数
    function isInteger(num){
        return Math.floor(num) === num
    }
};

上述代码我们还有一个优化的空间

就是如果 i = 1的时候不满足条件,假设此时对应的 target是一个接近 10 的非整数,那么在后续 i10的时候,找到对应的 target 肯定也不是一个整数

大概率是一个接近 1 的非整数,所以我们这里当 i 对应的 target 不满足条件的时候,i再走到接近 target的正整数是没有意义的

所以我们可以在 target 不满足条件后,将 max 调整为 target

如果通过上述描述没有讲清楚优化的逻辑,大家可以放开下方代码的 console 注释,给定一个 c=1002,查看调整 max=target 前后的循环次数即可。

var judgeSquareSum = function(c) {
    let max = Math.sqrt(c);
    if(isInteger(max)) return true;
    // 依次判断大于0的整数是否是满足条件的一个整数
    for(let i = 1;i<max;i++){
        const target = Math.sqrt(c-Math.pow(i,2))
        // console.log(i,target)
        if(isInteger(target)) return true;
        max = target;
    }
    return false;
    // 判断传入数值是否是整数
    function isInteger(num){
        return Math.floor(num) === num
    }
};

至此,我们就完成了leetcode-633-平方数之和

如有任何问题或建议,欢迎留言讨论!