633. 平方數(shù)之和

這道題有幾個(gè)數(shù)學(xué)做法比較有意思。

題目描述

給定一個(gè)非負(fù)整數(shù)c,你要判斷是否存在兩個(gè)整數(shù)ab,使得a^2+b^2=c。

解法

1. 利用等差數(shù)列公式

已知等差數(shù)列公式:
1 + 3 + 5 + ... + 2n-1 = (1 + 2n - 1) * n / 2 = n^2
而且有
n^2 + 2(n+1) - 1 = (n + 1) ^ 2
因此可以將c每次減少一個(gè)奇數(shù)(每次奇數(shù)增大2);看剩下的是否為一個(gè)平方數(shù)。
第一次減1,共減1的平方;
第二次減3,共減2的平方;
第三次減5,共減3的平方;
...
以此類推,直到減后為負(fù)數(shù)。

class Solution {
public:
  bool judgeSquareSum(int c) {
    int num1 = sqrt(c);
    if (num1 * num1 == c) { // 判斷c本身就是一個(gè)平方數(shù)
      return true;
    }
    num1 = c;
    for (int i = 1; i <= num1; i += 2) {
      num1 -= i; // 每次減去一個(gè)奇數(shù)
      int num2 = sqrt(num1);
      if (num2 * num2 == num1) {
        return true;
      }
    }
    return false; 
  }
};

2. 利用費(fèi)馬平方和定理

費(fèi)馬平方和定理(證明):

一個(gè)非負(fù)整數(shù) c 如果能夠表示為兩個(gè)整數(shù)的平方和,當(dāng)且僅當(dāng) c 的所有形如 4k + 3 的質(zhì)因子的冪均為偶數(shù)。

因此我們需要對(duì) c 進(jìn)行質(zhì)因數(shù)分解,再判斷所有形如 4k + 3 的質(zhì)因子的冪是否均為偶數(shù)即可。

class Solution {
public:
    bool judgeSquareSum(int c) {
        for (int base = 2; base * base <= c; base++) {
            // 如果不是因子,枚舉下一個(gè)
            if (c % base != 0) {
                continue;
            }

            // 計(jì)算 base 的冪
            int exp = 0;
            while (c % base == 0) {
                c /= base;
                exp++;
            }

            // 根據(jù) Sum of two squares theorem 驗(yàn)證
            if (base % 4 == 3 && exp % 2 != 0) {
                return false;
            }
        }

        // 例如 11 這樣的用例,由于上面的 for 循環(huán)里 base * base <= c ,base == 11 的時(shí)候不會(huì)進(jìn)入循環(huán)體
        // 因此在退出循環(huán)以后需要再做一次判斷
        return c % 4 != 3;
    }
};

3. 使用sqrt函數(shù)

枚舉,本題 c 的取值范圍在 [0,2^31?1],因此在計(jì)算的過(guò)程中可能會(huì)發(fā)生 int 型溢出的情況,需要使用 long 型避免溢出。

class Solution {
public:
  bool judgeSquareSum(int c) {
    for (long a = 0; a * a <= c; a++) {
      double b = sqrt(c - a * a)'
      if (b == (int)b) {
        return ture;
      }
    }
    return false;
  }
};

4. 雙指針

class Solution {
public:
    bool judgeSquareSum(int c) {
        long left = 0;
        long right = (int)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;
    }
};
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容