[LeetCode] 633. Sum of Square Numbers 平方數之和


 

Given a non-negative integer c, your task is to decide whether there're two integers a and b such that a2 + b2 = c.

Example 1:

Input: 5
Output: True
Explanation: 1 * 1 + 2 * 2 = 5

 

Example 2:

Input: 3
Output: False

 

這道題讓我們求一個數是否能由平方數之和組成,剛開始博主沒仔細看題,沒有看到必須要是兩個平方數之和,博主以為任意一個就可以。所以寫了個帶優化的遞歸解法,博主已經不是上來就無腦暴力破解的辣個青蔥騷年了,直接帶優化。可是居然對 14 返回 false,難道 14 不等於 1+4+9 嗎,結果仔細一看,必須要兩個平方數之和。好吧,那么遞歸都省了,直接判斷兩次就行了。我們可以從c的平方根,注意即使c不是平方數,也會返回一個整型數。然后我們判斷如果 i*i 等於c,說明c就是個平方數,只要再湊個0,就是兩個平方數之和,返回 true;如果不等於的話,那么算出差值 c - i*i,如果這個差值也是平方數的話,返回 true。遍歷結束后返回 false,參見代碼如下:

 

解法一:

class Solution {
public:
    bool judgeSquareSum(int c) {
        for (int i = sqrt(c); i >= 0; --i) {
            if (i * i == c) return true;
            int d = c - i * i, t = sqrt(d);
            if (t * t == d) return true;
        }
        return false;
    }
};

 

下面這種方法用到了 HashSet,從0遍歷到c的平方根,對於每個i*i,都加入 HashSet 中,然后計算 c - i*i,如果這個差值也在 HashSet 中,返回 true,遍歷結束返回 false,參見代碼如下:

 

解法二:

class Solution {
public:
    bool judgeSquareSum(int c) {
        unordered_set<int> s;
        for (int i = 0; i <= sqrt(c); ++i) {
            s.insert(i * i);
            if (s.count(c - i * i)) return true;
        }
        return false;
    }
};

 

上面兩種方法都不是很高效,來看下面這種高效的解法。論壇上有人稱之為二分解法,但是博主怎么覺得不是呢,雖然樣子很像,但是並沒有折半的操作啊。這里用a和b代表了左右兩個范圍,分別為0和c的平方根,然后 while 循環遍歷,如果 a*a + b*b 剛好等於c,那么返回 true;如果小於c,則a增大1;反之如果大於c,則b自減1,參見代碼如下:

 

解法三:

class Solution {
public:
    bool judgeSquareSum(int c) {
        long a = 0, b = sqrt(c);
        while (a <= b) {
            if (a * a + b * b == c) return true;
            else if (a * a + b * b < c) ++a;
            else --b;
        }
        return false;
    }
};

 

下面這種解法基於費馬平方和定理 Fermat's theorem on sums of two squares 的一般推廣形式:當某個數字的 4k+3 型的質數因子的個數均為偶數時,其可以拆分為兩個平方數之和(each prime that is congruent to 3 mod 4 appears with an even exponent in the prime factorization of the number)。那么我們只要統計其質數因子的個數,並且判讀,若其為 4k+3 型且出現次數為奇數的話直接返回 false。這里,我們從2開始遍歷,若能整除2,則計數器加1,並且c也要除以2。這樣我們找到都會是質數因子,因為非質數因子中的因子已經在之前被除掉了,這也是個 trick,需要自己好好想一下。最終在循環退出后,我們還要再判斷一下,若剩余的質數因子還是個 4k+3 型,那么返回 false,否則返回 true,參見代碼如下:

 

解法四:

class Solution {
public:
    bool judgeSquareSum(int c) {
        for (int i = 2; i * i <= c; ++i) {
            if (c % i != 0) continue;
            int cnt = 0;
            while (c % i == 0) {
                ++cnt;
                c /= i;
            }
            if (i % 4 == 3 && cnt % 2 != 0) return false;
        }
        return c % 4 != 3;
    }
};

 

類似題目:

Valid Perfect Square 

 

參考資料:

https://leetcode.com/problems/sum-of-square-numbers/

https://leetcode.com/problems/sum-of-square-numbers/discuss/104938/simple-c-solution

https://leetcode.com/problems/sum-of-square-numbers/discuss/104930/java-two-pointers-solution

https://leetcode.com/problems/sum-of-square-numbers/discuss/104932/hashset-java-quick-solution-one-for-loop

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM