一,题目详情
1,问题描述
小M拿到一个数组,她可以进行多次操作,每次操作可以选择两个元素 a_i 和 a_j,并选择 a_i 的一个因子 x,然后将 a_i 变为 a_i / x,并将 a_j 变为 a_j × x。她的目标是通过有限次操作,使得数组中的每个元素最多只包含一种素因子。
素因子的定义是:若 x 能被素数 p 整除,那么 p 是 x 的一个素因子。例如,12 的素因子有 2 和 3。
你的任务是判断是否有可能通过有限次操作,使数组中的每个元素最多只包含一种素因子。如果可以,输出 "Yes",否则输出 "No"。
2,测试样例
样例1:
输入:n = 4 ,a = [1, 2, 3, 4]
输出:'Yes'
样例2:
输入:n = 2 ,a = [10, 12]
输出:'No'
样例3:
输入:n = 3 ,a = [6, 9, 15]
输出:'Yes'
二,解题思路
1,问题分析
我们需要判断是否可以通过一系列操作,使得数组中的每个元素最多只包含一种素因子。关键在于分析所有元素的素因子种类,并判断是否可以通过操作将这些素因子分配到不同的元素中。
2,算法策略
核心思想是:所有元素的素因子种类数不能超过数组的长度。因为每个元素最终只能包含一种素因子,所以如果有超过数组长度的素因子种类,则无法满足条件。
具体步骤如下:
- 对于每个元素,获取其所有素因子。
- 收集所有元素的素因子,形成一个素因子集合。
- 如果素因子集合的大小小于等于数组长度,则返回 "Yes",否则返回 "No"。
3,逐步推演(以样例1为例)
输入:n = 4 ,a = [1, 2, 3, 4]
| 元素 | 素因子 |
|---|---|
| 1 | 无 |
| 2 | {2} |
| 3 | {3} |
| 4 | {2} |
素因子集合为 {2, 3},大小为2,小于等于4,所以返回 "Yes"。
三,代码实现
def solution(n: int, a: list) -> str:
def get_prime_factors(num):
factors = set()
if num == 1:
return factors
i = 2
while i * i <= num:
if num % i == 0:
factors.add(i)
while num % i == 0:
num //= i
i += 1
if num > 1:
factors.add(num)
return factors
primes = set()
for num in a:
primes.update(get_prime_factors(num))
return "Yes" if len(primes) <= n else "No"
1,复杂度分析
-
时间复杂度:O(m * sqrt(k)),其中 m 是数组长度,k 是数组中最大元素的大小
- 对于每个元素,获取素因子的时间复杂度为 O(sqrt(k))
-
空间复杂度:O(m + p),其中 p 是素因子的种类数
- 存储每个元素的素因子以及总的素因子集合
2,边界测试
if __name__ == '__main__':
# 常规测试
print(solution(4, [1, 2, 3, 4]) == "Yes")
print(solution(2, [10, 12]) == "No")
print(solution(3, [6, 9, 15]) == "Yes")
# 边界测试:所有元素为1
print(solution(3, [1, 1, 1]) == "Yes")
# 边界测试:元素包含多个素因子
print(solution(1, [6]) == "No")
四,总结
通过统计所有元素的素因子种类,我们实现了:
- 快速判断是否满足条件:通过比较素因子种类数和数组长度
- 高效的素因子分解:使用试除法获取每个元素的素因子
- 普适性:适用于所有整数数组
这种解法不仅高效,还易于理解和实现。当遇到“需要通过操作使数组元素满足某种条件”类问题时,分析问题的核心约束并转化为数学条件往往是解决问题的关键策略。