给定一个非负整数 c ,判断是否存在两个整数 a 和 b,其平方和等于c

给定c,寻找满足 a 2 + b 2 = c a^2+b^2=c a2+b2=c的a和b

其中 0 < = c < = 2 31 − 1 0 <= c <= 2^{31} - 1 0<=c<=2311.

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

解题整理:

1.暴力枚举

对于给定的非负整数 c,需要判断是否存在整数 a 和 b,使得 a 2 + b 2 = c a^2+b^2=c a2+b2=c。可以枚举 a和 b 所有可能的情况。但是暴力枚举有一些情况是没有必要的。例如:当 c = 20时,当 a = 1 的时候,枚举 b的时候,只需要枚举到 b = 5就可以结束了,这是因为 1 2 + 5 2 = 26 > 20 1^2+5^2=26>20 12+52=26>20当 b > 5 时,一定有 1 2 + b 2 > 20 1^2 + b^2 > 20 12+b2>20

在枚举 a 的同时,使用 sqrt 函数找出 b。注意:c 的取值范围在 [ 0 , 2 31 − 1 ] [0,2^{31} - 1] [0,2311],因此在计算的过程中可能会发生 int 型溢出的情况,需要使用long 型避免溢出。

class Solution {
    public boolean judgeSquareSum(int c) {
        for (long a = 0; a * a <= c; a++) {
            double b = Math.sqrt(c - a * a);
            if (b == (int) b) {
                return true;
            }
        }
        return false;
    }
}
2.使用双指针枚举

可以假设 a ≤ b a≤b ab。初始时 a = 0, b = c b = \sqrt{c} b=c ,进行如下操作:

  • 如果 a 2 + b 2 = c a^2 + b^2 = c a2+b2=c,我们找到了要求的一个解,返回 true \text{true} true
  • 如果 a 2 + b 2 < c a^2 + b^2 < c a2+b2<c,则a++;
  • 如果 a 2 + b 2 > c a^2 + b^2 > c a2+b2>c,则b–;
    当 a = b 时,结束查找,此时如果仍然没有找到整数 a 和 b 满足 a 2 + b 2 = c a^2 + b^2 = c a2+b2=c,则说明不存在要求的解,返回 false \text{false} false.

双指针为什么有用,可以参考链接

class Solution {
    public boolean judgeSquareSum(int c) {
        long left = 0;
        long right = (long) Math.sqrt(c);
        while (left <= right) {
            long sum = left * left + right * right;
            if (sum == c) {
                return true;
            } else if (sum > c) {
                right--;
            } else {
                left++;
            }
        }
        return false;
    }
}
3.使用双指针枚举

费马平方和定理: 一个非负整数 c c c 如果能够表示为两个整数的平方和,当且仅当 c c c 的所有形如 4 k + 3 4k + 3 4k+3 的质因子的幂均为偶数。

因此我们需要对 c c c 进行质因数分解,再判断所有形如 4 k + 3 4k + 3 4k+3的质因子的幂是否均为偶数即可。

class Solution {
    public boolean judgeSquareSum(int c) {
        for (int base = 2; base * base <= c; base++) {
            // 如果不是因子,枚举下一个
            if (c % base != 0) {
                continue;
            }

            // 计算 base 的幂
            int exp = 0;
            while (c % base == 0) {
                c /= base;
                exp++;
            }

            // 根据 Sum of two squares theorem 验证
            if (base % 4 == 3 && exp % 2 != 0) {
                return false;
            }
        }
        
        return c % 4 != 3;
    }
}
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山风wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值