Medium

题目描述

给定一个整数数组 nums,返回数组中恰好有四个因数的整数的因数之和。如果数组中没有这样的整数,则返回 0。

示例 1:

输入:nums = [21,4,7]
输出:32
解释:
21 有 4 个因数:1, 3, 7, 21
4 有 3 个因数:1, 2, 4
7 有 2 个因数:1, 7
答案是 21 的因数之和。

示例 2:

输入:nums = [21,21]
输出:64

示例 3:

输入:nums = [1,2,3,4,5]
输出:0

约束条件:

  • 1 <= nums.length <= 10^4
  • 1 <= nums[i] <= 10^5

提示:

  • 找出数组中每个元素的因数。
  • 你只需要循环到一个数的平方根来找到它的因数。

解题思路

解题思路

这道题要求找到数组中恰好有四个因数的数,并返回这些数的所有因数之和。

首先分析什么数恰好有四个因数:

  1. 质数的立方:如果 p 是质数,那么 p³ 的因数是 1, p, p², p³,共4个
  2. 两个不同质数的乘积:如果 p, q 是两个不同质数,那么 p×q 的因数是 1, p, q, p×q,共4个

基本解法是对每个数暴力枚举所有因数,时间复杂度较高。

优化解法:只需遍历到数字的平方根即可找到所有因数。对于每个数 n:

  • 从 1 遍历到 √n
  • 如果 i 能整除 n,则 i 和 n/i 都是因数
  • 需要注意 i = √n 时避免重复计算

具体步骤:

  1. 对数组中每个数字,计算其因数个数和因数之和
  2. 如果因数个数恰好是4,则将因数之和加入结果
  3. 返回总和

这种方法的时间复杂度是 O(n × √max(nums)),其中 n 是数组长度。

代码实现

class Solution {
public:
    int sumFourDivisors(vector<int>& nums) {
        int totalSum = 0;
        
        for (int num : nums) {
            int divisorCount = 0;
            int divisorSum = 0;
            
            // 只需要遍历到平方根
            for (int i = 1; i * i <= num; i++) {
                if (num % i == 0) {
                    divisorCount++;
                    divisorSum += i;
                    
                    // 如果i不是平方根,还要加上num/i
                    if (i * i != num) {
                        divisorCount++;
                        divisorSum += num / i;
                    }
                }
                
                // 提前剪枝:如果因数超过4个就不用继续了
                if (divisorCount > 4) break;
            }
            
            // 如果恰好有4个因数,加入总和
            if (divisorCount == 4) {
                totalSum += divisorSum;
            }
        }
        
        return totalSum;
    }
};
class Solution:
    def sumFourDivisors(self, nums: List[int]) -> int:
        total_sum = 0
        
        for num in nums:
            divisor_count = 0
            divisor_sum = 0
            
            # 只需要遍历到平方根
            i = 1
            while i * i <= num:
                if num % i == 0:
                    divisor_count += 1
                    divisor_sum += i
                    
                    # 如果i不是平方根,还要加上num//i
                    if i * i != num:
                        divisor_count += 1
                        divisor_sum += num // i
                
                # 提前剪枝:如果因数超过4个就不用继续了
                if divisor_count > 4:
                    break
                    
                i += 1
            
            # 如果恰好有4个因数,加入总和
            if divisor_count == 4:
                total_sum += divisor_sum
        
        return total_sum
public class Solution {
    public int SumFourDivisors(int[] nums) {
        int totalSum = 0;
        
        foreach (int num in nums) {
            int divisorCount = 0;
            int divisorSum = 0;
            
            // 只需要遍历到平方根
            for (int i = 1; i * i <= num; i++) {
                if (num % i == 0) {
                    divisorCount++;
                    divisorSum += i;
                    
                    // 如果i不是平方根,还要加上num/i
                    if (i * i != num) {
                        divisorCount++;
                        divisorSum += num / i;
                    }
                }
                
                // 提前剪枝:如果因数超过4个就不用继续了
                if (divisorCount > 4) break;
            }
            
            // 如果恰好有4个因数,加入总和
            if (divisorCount == 4) {
                totalSum += divisorSum;
            }
        }
        
        return totalSum;
    }
}
var sumFourDivisors = function(nums) {
    function getDivisors(n) {
        let divisors = [];
        for (let i = 1; i * i <= n; i++) {
            if (n % i === 0) {
                divisors.push(i);
                if (i !== n / i) {
                    divisors.push(n / i);
                }
            }
        }
        return divisors;
    }
    
    let sum = 0;
    for (let num of nums) {
        let divisors = getDivisors(num);
        if (divisors.length === 4) {
            sum += divisors.reduce((a, b) => a + b, 0);
        }
    }
    return sum;
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n × √max(nums))n 是数组长度,需要对每个数计算因数,每次计算需要 O(√num) 时间
空间复杂度O(1)只使用了常数个变量存储中间结果