← 返回题目列表

完美数如何只枚举到平方根判断因子和?(LeetCode 507)

简单 第 25 / 27 题 更新于 2026/08/01
数学因子平方根枚举完美数

简化版

完美数是等于除自身外所有正因子之和的数。判断时先把 sum 设为 1,然后枚举 i 从 2 到 sqrt(n):如果 i 是因子,就同时加入 in / i。最后看 sum == n。注意 n <= 1 不是完美数。

详细版

boolean 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;
            if (i != num / i) sum += num / i;
        }
    }
    return sum == num;
}

例如 28 的真因子是 1,2,4,7,14,和为 28,所以是完美数。枚举到平方根即可,因为因子总是成对出现。

完整版教学

一、完美数的定义

完美数要求:

num = 所有真因子之和

真因子是不包含数字自身的正因子。例如:

28 的真因子:1, 2, 4, 7, 14
1 + 2 + 4 + 7 + 14 = 28

所以 28 是完美数。

二、为什么从 sum = 1 开始

对于大于 1 的整数,1 一定是它的真因子。为了避免从 1 枚举到平方根时把自身也加进去,通常先把 sum 设为 1,然后从 2 开始枚举。

num初始 sum原因
2811 是真因子
611 是真因子
1不适用1 没有正真因子和为 1

易错点:num <= 1 要先返回 false,否则 sum=1 会把 1 误判成完美数。

三、因子为什么成对出现

如果 i 能整除 num,那么 num / i 也是因子。

28:
2 * 14
4 * 7

所以枚举到平方根就够了。小因子在左,大因子在右,一次发现两个。

四、平方数因子不能加两次

如果 num = 36,当 i = 6 时,配对因子也是 6。这时只能加一次:

if (i != num / i) sum += num / i;

否则平方根会被重复计算,导致因子和偏大。

五、循环条件的溢出问题

常见写法是 i * i <= num。在本题范围较小时没问题;如果输入可能很大,可以写成:

for (int i = 2; i <= num / i; i++)

这样避免 i * i 溢出。

六、复杂度与提前退出

枚举到平方根,时间复杂度 O(sqrt(n)),空间 O(1)。可以在 sum > num 时提前返回 false,因为正因子和只会继续增加。

如果 sum 已经超过 num,再加因子不会变小

提前退出不是必须,但能减少部分输入的运行时间。

七、常见误区与追问

  • 误区:把 num 自身也加入因子和。 完美数看真因子,不包含自身。
  • 误区:把 1 判成完美数。 num <= 1 应直接 false。
  • 误区:平方根因子加两次。i == num / i 时只能加一次。
  • 追问:为什么只枚举到平方根? 因子成对出现,一个小于等于平方根,另一个大于等于平方根。
  • 追问:复杂度是多少? 时间 O(sqrt(n)),空间 O(1)
  • 追问:能不能用欧几里得-欧拉定理? 可以生成偶完美数,但判断题用因子枚举更直接。

八、加强记忆

完美数判断模板是:num <= 1 false,sum = 1,从 2 枚举到平方根,发现因子就加一对,平方根只加一次。它考的是“真因子”和“因子成对”,别把自身混进去。