LeetCode 1390. 四因数
题目描述


题意分析
对数组中的每个正整数,判断它是否恰好有四个不同的正因数。如果满足条件,就把这四个因数的和计入总答案;否则该整数贡献零。
正因数包括一和这个数自身,求的是因数之和,不是满足条件的整数之和。数组中相同整数若出现多次,也应按每次出现分别贡献。
解法:枚举因子
核心思路
[!blue]
因数总是成对出现:如果
d能整除x,另一因数就是x / d。一对因数中至少有一个不超过平方根,所以只枚举满足d * d <= x的候选,就能覆盖全部因数,不必从一检查到x。发现一对因数时,先计入
d,若另一因数与它不同,再计入x / d。两者相同只会发生在完全平方数的平方根处,这时必须只计一次,否则会把同一个因数重复统计。对当前整数维护已发现因数个数
count和它们的和sum。若个数超过四,可以立即返回零,因为继续枚举只会增加因数,不可能重新变回四个。反过来,刚发现四个时还不能认定成功,后面可能继续找到其他因数。只有扫描完平方根范围、确认恰好四个时,才能贡献当前因数和。每个数组元素都独立执行这项检查,最后累加贡献。
解题步骤
- 对当前整数初始化因数个数和因数和为零。
- 从一枚举到平方根,不整除就跳过。
- 整除时加入当前因数及配对因数,平方根重合时只加一次。
- 个数超过四就立即贡献零;完整枚举后恰好四个才贡献因数和。
- 汇总所有数组元素的贡献并返回。
代码实现
class Solution {
public int sumFourDivisors(int[] nums) {
int total = 0;
for (int x : nums) {
total += divisorSumIfFour(x);
}
return total;
}
private int divisorSumIfFour(int x) {
int count = 0;
int sum = 0;
for (int d = 1; d * d <= x; d++) {
if (x % d != 0) {
continue;
}
// 因数成对出现,只枚举其中不超过平方根的一侧。
int other = x / d;
count++;
sum += d;
// 完全平方数的平方根只计算一次。
if (other != d) {
count++;
sum += other;
}
// 数量只会增加,超过四个即可失败;等于四个不能提前成功。
if (count > 4) {
return 0;
}
}
return count == 4 ? sum : 0;
}
}
func sumFourDivisors(nums []int) int {
total := 0
for _, x := range nums {
total += divisorSumIfFour(x)
}
return total
}
func divisorSumIfFour(x int) int {
count, sum := 0, 0
for d := 1; d*d <= x; d++ {
if x%d != 0 {
continue
}
// 因数成对出现,只枚举其中不超过平方根的一侧。
other := x / d
count++
sum += d
// 完全平方数的平方根只计算一次。
if other != d {
count++
sum += other
}
// 数量只会增加,超过四个即可失败;等于四个不能提前成功。
if count > 4 {
return 0
}
}
if count == 4 {
return sum
}
return 0
}
复杂度分析
- 时间复杂度:$O(\sum_i\sqrt{nums_i})$,每个整数最多枚举到其平方根,超过四因数时可以提前停止。
- 辅助空间复杂度:$O(1)$,只保存当前整数的计数、因数和以及总答案。
关键点总结
[!green]
- 成对枚举把检查范围缩小到平方根,同时覆盖一和自身。
- 平方根对应同一个因数,只计一次。
- 超过四个可立即失败,恰好四个必须等枚举完成才能确认。
易错点总结
[!yellow]
- 找到四个就提前成功,会遗漏后面出现的第五个或更多因数。
- 平方根重复计数会把实际因数数量较少的平方数误判为合格。
- 只累加
d而漏掉配对值x / d,会同时算错数量和总和。- 每个整数要重置局部统计,不能把前一个数的因数数量沿用下来。
- 合格时累加的是全部因数的和,不是当前整数本身。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 507. 完美数 | 简单 | 同样成对枚举因子并累计和,本题还要求因子总数恰为4。 |
| 补充题 153. 整数的质因数分解 | 简单 | 四因数结构只可能是素数立方或两个不同素数之积,可由质因数重数理解。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!