题目地址:
https://leetcode.com/problems/largest-component-size-by-common-factor/
给定一个长 n n n的非空正整数数组 A A A,考虑一个由 A A A中数字作为顶点的一个图,两个数字 x , y x,y x,y有边相连当且仅当 gcd ( x , y ) > 1 \gcd(x,y)>1 gcd(x,y)>1。问该图的最大连通块的元素数。
可以开个并查集,枚举每个数 A [ i ] A[i] A[i],然后将 A [ i ] A[i] A[i]与它的所有素因子union起来(关于素因子分解,可以参考https://blog.csdn.net/qq_46105170/article/details/113813420)。最后只需要看一下含 A A A中数最多的那个连通块里,含多少个 A A A中的数即可。代码如下:
import java.util.HashMap;
import java.util.Map;
public class Solution {
private int[] parent;
private int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]);
}
return parent[x];
}
private void union(int x, int y) {
int px = find(x), py = find(y);
if (px == py) {
return;
}
parent[px] = py;
}
public int largestComponentSize(int[] A) {
int max = 0;
for (int x : A) {
max = Math.max(max, x);
}
parent = new int[max + 1];
for (int i = 0; i < parent.length; i++) {
parent[i] = i;
}
for (int x : A) {
// 进行素因子分解
int y = x;
for (int i = 2; i <= y / i; i++) {
if (y % i == 0) {
while (y % i == 0) {
y /= i;
}
union(x, i);
}
}
// 如果y没除尽,那说明y自己就是素数,也需要union起来
if (y > 1) {
union(x, y);
}
}
int res = 0;
Map<Integer, Integer> map = new HashMap<>();
for (int x : A) {
int px = find(x);
map.put(px, map.getOrDefault(px, 0) + 1);
}
for (int cnt : map.values()) {
res = Math.max(res, cnt);
}
return res;
}
}
时间复杂度 O ( max A + ∑ A [ i ] + n log ∗ n ) O(\max A+\sum \sqrt {A[i]}+n\log ^*n) O(maxA+∑A[i]+nlog∗n),空间 O ( max A + n ) O(\max A+n) O(maxA+n)。