Given a non-empty array of unique positive integers A, consider the following graph:
- There are
A.lengthnodes, labelledA[0]toA[A.length - 1]; - There is an edge between
A[i]andA[j]if and only ifA[i]andA[j]share a common factor greater than 1.
Return the size of the largest connected component in the graph.
Related Topics:
Math, Union Find
The number of elements is big. Can we reduce the scale? Consider all the primes that are factors of numbers in A.
For each number A[i], we union all the factors of A[i]. In this way, A[i]s are grouped according to factors. The size of the biggest group is the result.
// OJ: https://leetcode.com/problems/largest-component-size-by-common-factor/
// Author: github.com/lzl124631x
// Time: O(N * sqrt(W)) where N is length of A, W is max(A[i])
// Space: O(N)
class UnionFind {
vector<int> id;
public:
UnionFind(int N) : id(N) {
iota(begin(id), end(id), 0);
}
int find(int a) {
return id[a] == a ? a : (id[a] = find(id[a]));
}
void connect(int a, int b) {
int p = find(a), q = find(b);
if (p == q) return;
id[p] = q;
}
};
class Solution {
vector<int> factors(int n) {
vector<int> ans;
for (int i = 2; i * i <= n; ++i) {
if (n % i) continue;
ans.push_back(i);
while (n % i == 0) n /= i;
}
if (n > 1 || ans.empty()) ans.push_back(n);
return ans;
}
public:
int largestComponentSize(vector<int>& A) {
vector<vector<int>> F;
unordered_map<int, int> m;
int i = 0, ans = 0;
for (int n : A) {
auto f = factors(n);
F.push_back(f);
for (int x : f) {
if (!m.count(x)) m[x] = i++;
}
}
UnionFind uf(m.size());
for (auto &f : F) {
for (int x : f) uf.connect(m[f[0]], m[x]);
}
vector<int> cnt(m.size());
for (auto &f : F) ans = max(ans, ++cnt[uf.find(m[f[0]])]);
return ans;
}
};

