【并查集】A013_LC_按公因数计算最大组件大小(试除法求约数 / 质数打表)

一、Problem

给定一个由不同正整数的组成的非空数组 A,考虑下面的图:

有 A.length 个节点,按从 A[0] 到 A[A.length - 1] 标记;
只有当 A[i] 和 A[j] 共用一个大于 1 的公因数时,A[i] 和 A[j] 之间才有一条边。
返回图中最大连通组件的大小。

示例 1:

输入:[4,6,15,35]
输出:4
在这里插入图片描述
提示:

1 <= A.length <= 20000
1 <= A[i] <= 100000

二、Solution

方法一:并查集

【并查集】A013_LC_按公因数计算最大组件大小(试除法求约数 / 质数打表)_第1张图片
因为两个数之间是通过因子相关联起来的,这里我们有两个方案:

  1. 枚举 A[0]…A[n-1],将每个数与其因子合并
  2. 先用质数打表,然后双重循环枚举 n u m 1 , n u m 2 ∈ [ 2 , m a x v ] num1, num2 ∈ [2, maxv] num1,num2[2,maxv],将具有大于 1 的公约数的两个数 num1, num2 合并
class Solution {
     
public:
	vector<int> fa;
	void merge(int p, int q) {
     
		int pID = find(p), qID = find(q);
		if (pID != qID)
			fa[pID] = qID;
	}
	int find(int p) {
     
		while (p != fa[p]) {
     
			p = fa[p];
			fa[p] = fa[fa[p]];
		}
		return p;
	}
    int largestComponentSize(vector<int>& A) {
     
    	int ma = *max_element(A.begin(), A.end());
    	fa.resize(ma+1);
    	for (int i = 1; i <= ma; i++) fa[i] = i;

    	for (int n : A)
        for (int i = 2; i <= n/i; i++) {
     
            if (n % i == 0) {
     
                merge(n, i);
                if (i != n/i)
                	merge(n, n/i);
            }
        }
    	vector<int> cnt(ma+1, 0);
    	int ans = 0;
    	for (int n : A) {
     
    		int f = find(n);
    		cnt[f]++;
    		if (cnt[f] > ans) ans = cnt[f];
    	}
    	return ans;
    }
};

复杂度分析

  • 时间复杂度: O ( n × s q r t ( v ) ) O(n × sqrt(v)) O(n×sqrt(v)),v 为数值
  • 空间复杂度: O ( m a x ) O(max) O(max)

方法二:质数打表

不太懂为什么要和质数联系在一起


复杂度分析

  • 时间复杂度: O ( ) O() O()
  • 空间复杂度: O ( ) O() O()

你可能感兴趣的:(【并查集】A013_LC_按公因数计算最大组件大小(试除法求约数 / 质数打表))