Medium
题目描述
给你一个正整数数组 nums,返回 nums 中所有元素乘积的不同质因数的数目。
注意:
- 大于 1 的数被称为质数,当且仅当它只能被 1 和自身整除。
- 如果
val2 / val1是一个整数,则整数val1是另一个整数val2的一个因数。
示例 1:
输入:nums = [2,4,3,7,10,6]
输出:4
解释:
nums 中所有元素的乘积是:2 * 4 * 3 * 7 * 10 * 6 = 10080 = 2^5 * 3^2 * 5 * 7 。
共有 4 个不同的质因数,所以返回 4 。
示例 2:
输入:nums = [2,4,8,16]
输出:1
解释:
nums 中所有元素的乘积是:2 * 4 * 8 * 16 = 1024 = 2^10 。
共有 1 个不同的质因数,所以返回 1 。
提示:
1 <= nums.length <= 10^42 <= nums[i] <= 1000
解题思路
解题思路
这道题要求找到数组所有元素乘积的不同质因数个数。关键insight是:我们不需要真的计算乘积,因为乘积会非常大而溢出。
核心思路是利用质因数分解的性质:
- 如果
a = p1^x1 * p2^x2 * ... * pk^xk - 如果
b = p1^y1 * p2^y2 * ... * pk^yk - 那么
a * b = p1^(x1+y1) * p2^(x2+y2) * ... * pk^(xk+yk)
因此,乘积的质因数就是各个数的质因数的并集。
算法步骤:
- 对每个数字进行质因数分解
- 将所有质因数放入集合中去重
- 返回集合的大小
质因数分解方法:
- 从 2 开始到 √n,如果 i 能整除 n,则 i 是质因数
- 持续除以 i 直到不能整除,然后检查下一个数
- 如果最后 n > 1,说明 n 本身是个质因数
时间复杂度主要取决于质因数分解,由于数字范围不超过 1000,分解效率很高。
代码实现
class Solution {
public:
int distinctPrimeFactors(vector<int>& nums) {
unordered_set<int> primes;
for (int num : nums) {
// 质因数分解
for (int i = 2; i * i <= num; i++) {
if (num % i == 0) {
primes.insert(i);
while (num % i == 0) {
num /= i;
}
}
}
// 如果num > 1,说明num本身是一个质因数
if (num > 1) {
primes.insert(num);
}
}
return primes.size();
}
};
class Solution:
def distinctPrimeFactors(self, nums: List[int]) -> int:
primes = set()
for num in nums:
# 质因数分解
i = 2
while i * i <= num:
if num % i == 0:
primes.add(i)
while num % i == 0:
num //= i
i += 1
# 如果num > 1,说明num本身是一个质因数
if num > 1:
primes.add(num)
return len(primes)
public class Solution {
public int DistinctPrimeFactors(int[] nums) {
HashSet<int> primes = new HashSet<int>();
foreach (int num in nums) {
int current = num;
// 质因数分解
for (int i = 2; i * i <= current; i++) {
if (current % i == 0) {
primes.Add(i);
while (current % i == 0) {
current /= i;
}
}
}
// 如果current > 1,说明current本身是一个质因数
if (current > 1) {
primes.Add(current);
}
}
return primes.Count;
}
}
/**
* @param {number[]} nums
* @return {number}
*/
var distinctPrimeFactors = function(nums) {
const primes = new Set();
for (let num of nums) {
for (let i = 2; i * i <= num; i++) {
while (num % i === 0) {
primes.add(i);
num /= i;
}
}
if (num > 1) {
primes.add(num);
}
}
return primes.size;
};
复杂度分析
| 复杂度类型 | 值 |
|---|---|
| 时间复杂度 | O(n × √m) |
| 空间复杂度 | O(k) |
其中:
- n 是数组长度
- m 是数组中元素的最大值
- k 是不同质因数的个数(最多为所有小于等于1000的质数个数,约168个)