Swift - LeetCode - 完美数

91 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第24天,点击查看活动详情

题目

对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」

给定一个 整数 n, 如果是完美数,返回 true;否则返回 false

示例 1:

  • 输入: num = 28
  • 输出: true
  • 解释: 28 = 1 + 2 + 4 + 7 + 14 1, 2, 4, 7, 和 14 是 28 的所有正因子。

示例 2:

  • 输入: num = 7
  • 输出: false

方法一:枚举

思路及解法

我们可以枚举 num 的所有真因子,累加所有真因子之和,记作 sum。若 sum=num$ 则返回 true,否则返回 false

在枚举时,我们只需要枚举不超过 num\sqrt{num} 的数。这是因为如果 num 有一个大于 num\sqrt{num} 的因数 d, 那么它一定有一个小于 num\sqrt{num} 的因数 numd\dfrac{\textit{num}}{d}

在枚举时,若找到了一个因数 d,那么就找到了因数 numd\dfrac{\textit{num}}{d}。注意当 dd=numd\cdot d=\textit{num} 时这两个因数相同,此时不能重复计算。

代码

class Solution {
    func checkPerfectNumber(_ num: Int) -> Bool {
        if 1 == num {
            return false
        }
        var d: Int = 2
        var sum: Int = 1
        while d * d <= num {
            if num % d == 0 {
                sum += d
                if d * d < num {
                    sum += num / d
                }
            }
            d += 1
        }
        return sum == num
    }
}

复杂度分析

  • 时间复杂度:O(num)O(\sqrt{num})

  • 空间复杂度:O(1)O(1)

方法二:数学

思路及解法

根据欧几里得-欧拉定理,每个偶完全数都可以写成

2p1(2p1)2^{p-1}(2^p-1)

的形式,其中 pp 为素数且 2p12^p-1 为素数。

由于目前奇完全数还未被发现,因此题目范围 [1,108][1,10^8] 内的完全数都可以写成上述形式。

这一共有如下 5 个:

6, 28, 496, 8128, 33550336

代码

class Solution {
    func checkPerfectNumber(_ num: Int) -> Bool {
        return num == 6 || num == 28 || num == 496 || num == 8128 || num == 33550336
    }
}

复杂度分析

  • 时间复杂度:O(1)O(1)

  • 空间复杂度:O(1)O(1)