返回

探索LeetCode 107:952- 按公因数计算最大组件大小

前端

前言

踏入算法的奥妙世界,我们来到了LeetCode的第107站,迎接我们的是一道巧妙的图论问题——952- 按公因数计算最大组件大小。这道题的本质是寻找图中的连通分量,并找出其中最大的那个,而图中的节点和边是由给定数组的数字及其公因数所组成的。让我们踏上这段探索之旅,领略算法之美。

算法解析

连通分量
连通分量是指图中一组连通的节点,它们之间至少存在一条路径相连。找出最大连通分量就是找到连接最多的节点组。

公因数
题目要求我们以公因数作为边的依据构建图。对于给定的数组 nums,如果两个数字 i 和 j 存在公因数,那么我们就在图中添加一条从 i 到 j 的边。

算法步骤

  1. 初始化并查集: 创建并查集数据结构,它可以高效地管理节点的连通性。
  2. 遍历数组: 依次遍历数组 nums 中的每个数字 i。
  3. 分解质因数: 对于每个数字 i,分解其质因数,并将其存储在集合中。
  4. 遍历质因数: 对于 i 的每个质因数 p,查找集合中是否包含 p 的倍数。如果是,则使用并查集合并 i 和该倍数所在的连通分量。
  5. 统计最大连通分量: 在处理完所有数字后,遍历并查集,统计每个连通分量的节点数量。最大的连通分量就是我们需要的答案。

代码实现

from collections import defaultdict

def max_component_size(nums):
    # 初始化并查集
    parent = {n: n for n in nums}
    rank = {n: 0 for n in nums}

    # 遍历数组
    for num in nums:
        # 分解质因数
        factors = set()
        i = 2
        while num > 1:
            if num % i == 0:
                factors.add(i)
                while num % i == 0:
                    num //= i
            i += 1

        # 遍历质因数
        for factor in factors:
            # 查找集合中是否包含 factor 的倍数
            p = factor
            while p in parent:
                p = parent[p]

            # 合并连通分量
            if p != num:
                if rank[p] < rank[num]:
                    parent[p] = num
                    rank[num] += 1
                else:
                    parent[num] = p
                    rank[p] += 1

    # 统计最大连通分量
    max_size = 0
    for n in nums:
        p = find_parent(n, parent)
        max_size = max(max_size, rank[p])

    return max_size

def find_parent(node, parent):
    if parent[node] != node:
        parent[node] = find_parent(parent[node], parent)
    return parent[node]

复杂度分析

  • 时间复杂度:O(n log n),其中 n 为数组 nums 的长度。
  • 空间复杂度:O(n),存储并查集和质因数集合。

总结

这道题目融合了图论、并查集和质因数分解的知识,考察了算法设计和数据结构的应用能力。通过将数组中的数字及其公因数转化为图中的节点和边,我们巧妙地解决了寻找最大连通分量的难题。算法的实现清晰高效,展示了算法在实际问题中的应用。探索LeetCode的旅程仍在继续,让我们期待下一次的挑战和收获。