1. 程式人生 > >[LeetCode] 507.Perfect Number 完美數

[LeetCode] 507.Perfect Number 完美數

對於一個 正整數,如果它和除了它自身以外的所有正因子之和相等,我們稱它為“完美數”。
給定一個 正整數 n, 如果他是完美數,返回 True,否則返回 False。
注意:輸入的數字 n 不會超過 100,000,000. (1e8)
例:輸入: 28
輸出: True
解釋: 28 = 1 + 2 + 4 + 7 + 14

這是一道有關完美數的題目。完美數的定義如上所說,如果一個數n的因數和 (包括n) 記作 f(n),我們把令 f(n) = 2n的數稱為完美數,令 f(n) < 2n 的數稱為虧數,令 f(n) > 2n 的數稱為盈數。

思路

簡單的,我們可以得出 1不是完美數。對於 n>1 的情況,考慮一對對的因數相加,例如,對28有[1,28],[2,14],[4,7],因為1必定是n的因子,可以提前加上,那麼尋找其他因子的範圍縮小至[2, sqrt(n)]。
遍歷這一區間,如果數i可以被n整除,那麼我們把 i 和 n/i 都加上,當 n 是完全平方數時,相同的因子加了兩次(即i與 n/i = i),所以要減掉一次當前的 i。還有就是在遍歷的過程中如果累積和sum大於n了,直接返回false即可。程式碼如下。

程式碼

class Solution {
public:
    bool checkPerfectNumber(int num) {
        if (num == 1) return false;
        int sum = 1;
        for (int i = 2; i * i <= num; ++i) {
            if (num % i == 0) 
                sum += (i + num / i);
            if (i * i == num)
                sum -= i;
            if (sum > num) 
                return false;
        }
        return sum == num;
    }
};

歷史

事實上,完美數的尋找已經頗有歷史,從古希臘的畢達哥拉斯到尤拉,再到現代的計算機,不少數學家都在不停地尋找完美數及推測它的性質。由相關數學知識可得,完美數的數量分佈極其零散,前七個完美數為6、28、496、8,128、33,550,336、8,589,869,056、137,438,691,328。
對於此題1e8的範圍內,僅需判斷前五個完美數即可。程式碼如下。

程式碼

class Solution {
public:
    bool checkPerfectNumber(int num) {
        return num==6 || num==28 || num==496 || num==8128 || num==33550336;
    }
};