题目解析 17题 小M的数组交换| 豆包MarsCode AI刷题

77 阅读4分钟

题目回顾:

问题核心

我们需要判断是否可以通过一系列操作(选择两个元素a[i]a[j],并用a[i]的一个因子x进行变换),使得数组中的每个元素最多只包含一种素因子。关键在于理解如何重新分配素因子,以确保每个元素最终只含有一种素因子。

解决方案的思路

  1. 确定所有不同的素因子:首先,我们需要找出数组中所有数字的所有不同素因子。
  2. 检查素因子种类数量:然后,我们检查这些不同素因子的数量是否不超过数组的长度。如果不超过,那么我们可以将每种素因子分配给一个或多个元素,从而满足条件;否则,无法达到目标。

具体步骤

  • 提取素因子:对于数组中的每个数,使用辅助函数prime_factors来提取其所有素因子。这个函数会返回一个Counter对象,其中键是素因子,值是该素因子出现的次数。
  • 收集唯一素因子:我们将所有找到的素因子放入一个集合unique_prime_factors中,这样可以自动去除重复的素因子。
  • 验证素因子种类数量:最后,我们检查集合unique_prime_factors的大小是否超过数组长度n。如果不超过,说明可以通过适当的操作使每个元素最多只包含一种素因子;否则,无法实现。

代码解答如下 本题使用Py进行解答:

from collections import Counter
from math import sqrt

def prime_factors(n):
    """返回数字n的所有素因子及其对应的次数"""
    factors = Counter()
    # 处理2这个特殊的偶数素因子
    while n % 2 == 0:
        factors[2] += 1
        n //= 2
    # 检查奇数素因子
    for i in range(3, int(sqrt(n)) + 1, 2):
        while n % i == 0:
            factors[i] += 1
            n //= i
    if n > 2:  # 如果剩余的是一个大于2的素数
        factors[n] += 1
    return factors

def solution(n: int, a: list) -> str:
    unique_prime_factors = set()
    
    for num in a:
        # 更新总的素因子集合
        unique_prime_factors.update(prime_factors(num).keys())
    
    # 检查不同的素因子种类数量是否超过数组长度
    if len(unique_prime_factors) > n:
        return "No"
    
    return "Yes"

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. 素因子分解

    • 对于每个数组中的数字,我们需要找到其所有的素因子。这是通过一个简单的迭代过程完成的,其中我们首先处理2(唯一的偶数素数),然后处理奇数素数直到sqrt(n)。如果在处理完所有可能的素因子后还剩下大于2的数,那么这个数本身就是一个素数。
    • 这个过程的时间复杂度大约是O(√n),其中n是我们要分解的数字。
  2. 集合操作

    • 我们使用Python的集合(set)来存储所有不同的素因子。集合的特点是它自动去重,因此我们可以很容易地得到所有不同的素因子种类。
    • 使用集合的操作如添加元素(.add())和更新集合(.update())都是平均时间复杂度为O(1)的操作。
  3. 计数器(Counter)

    • prime_factors函数中,我们使用了collections.Counter来统计每个素因子出现的次数。虽然在这个特定问题中我们最终只关心不同素因子的数量,但使用Counter可以方便地收集和处理这些信息。
    • Counter的更新操作也是高效的,通常是O(1)。
  4. 逻辑判断

    • 最后的逻辑判断是比较不同素因子的种类数量与数组长度。如果不同素因子的种类数量不超过数组长度,那么我们可以通过适当的操作使每个元素最多只包含一种素因子;否则,无法实现目标。
    • 这一步骤的时间复杂度是O(1),因为它只是对集合大小进行一次比较。

算法总结

  • 素因子分解:对于每个数字,时间复杂度为O(√n)。
  • 集合操作:用于存储和去重素因子,操作时间复杂度为O(1)。
  • 计数器:用于统计素因子出现的次数,更新操作时间复杂度为O(1)。
  • 逻辑判断:检查素因子种类数量是否超过数组长度,时间复杂度为O(1)。

整体复杂度分析

  • 对于整个数组,假设数组长度为N,每个数字的最大值为M,那么总的时间复杂度大约是O(N * √M)。这是因为我们需要对数组中的每个数字执行素因子分解。
  • 空间复杂度主要取决于存储素因子的集合和计数器,最坏情况下为O(N * log M),因为每个数字的素因子分解结果可能包含log M个素因子。