原题链接 https://leetcode.com/problems/largest-component-size-by-common-factor/submissions/
题意就不再做解释了,直接上题解:
方法一:简单并查集--超时
只要任何两个数之间有相同的因子,那么就把他们连接到一起,这样可以把每个数字和它的所有因子进行链接,最后统计哪个因子上面的数字最多即可,代码比较好懂
class Solution {
vector<int>father;
int findfather(int n){
while(n!=father[n]){
n = father[n];
}
return n;
}
void merge(int a,int b){
int aa = findfather(a);
int bb = findfather(b);
if(aa!=bb)
father[aa]=bb;
}
public:
int largestComponentSize(vector<int>& A) {
int maxnum = 0;
for(auto x:A)
maxnum = max(maxnum,x);
father = vector<int>(maxnum+1,-1);
for(int i = 0;i<maxnum+1;i++)
father[i] = i;
int n = A.size();
for(auto x:A)
for(int i = 2;i<=sqrt(x);i++)
if(x%i==0){
merge(x,i);
merge(x,x/i);
}
unordered_map<int,int>mp;
for(auto x:A){
// cout<<father[x]<<endl;
mp[findfather(x)]++;
}
int res = 0;
for(auto x:mp)
res = max(res,x.second);
return res;
}
};
方法二
然鹅却超时了,怀疑是因为数组太长,寻根部分花了较多时间,于是考虑对每个数字分别分解质因数,开一个二维 vector 记录每个质因数所对应的数字有哪些,然后将其记录的所有数字通过并查集连接在一起,最后的结果是最大的集合,代码参考:https://www.acwing.com/solution/LeetCode/content/646/
class Solution {
public:
vector<int> fa, sz;
int find(int x) {
return x != fa[x] ? fa[x] = find(fa[x]) : x;
}
int largestComponentSize(vector<int>& A) {
int n = A.size(), ans = 0;
vector<vector<int>> num(100001);
for (int i = 0; i < n; i++) {
int x = A[i];
for (int y = 2; y * y <= x; y++) {
if (x % y == 0)
num[y].push_back(i);
while (x % y == 0)
x /= y;
}
if (x > 1)
num[x].push_back(i);
}
fa = vector<int>(n);
sz = vector<int>(n);
for (int i = 0; i < n; i++) {
fa[i] = i;
sz[i] = 1;
}
for (int i = 1; i <= 100000; i++)
for (int j = 1; j < num[i].size(); j++) {
int x = num[i][0], y = num[i][j];
int fx = find(x), fy = find(y);
if (fx != fy) {
if (sz[fx] < sz[fy]) {
fa[fy] = fx;
sz[fx] += sz[fy];
}
else {
fa[fx] = fy;
sz[fy] += sz[fx];
}
}
}
for (int i = 0; i < n; i++)
if (i == find(i))
ans = max(ans, sz[i]);
return ans;
}
};