LeetCode/按公因数计算最大组件大小(并查集)
给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图:
- 有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记
- 只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之间才有一条边
返回图中最大连通组件的大小
1. 并查集(从后往前)
//每个数从后往前按公因数建冗余集合,根据公因数合并集合,根节点为当前数
class Solution {
public:
vector<int> parent;
int largestComponentSize(vector<int>& nums) {
// 根据最大值确定集合上限
int maxNum = INT_MIN;
for (int num : nums)
maxNum = max(maxNum, num);
// 最大的范围是 maxNum + 1, 而不是maxNum,要考虑0的情况
parent.resize(maxNum+1);
for (int i = 0; i < parent.size(); ++i)
parent[i] = i;//每个数为一个集合
// 一簇公因数建立一个集合,公因数存在相同则集合合并
for (int num : nums)
for (int i = sqrt(num); i >= 2; --i)//从后往前
if (num % i == 0) // 取可以被整除的情况,即可连通
{
unions(num, i);//大的并小的,本质上也是根据公因数去并另一个集合
unions(num, num / i);
}
// 再次遍历去计数
unordered_map<int, int> cnt;
for (int num : nums)
++cnt[find(num)];
int res = 0;
for (auto iter = cnt.begin(); iter != cnt.end(); ++iter)
res = max(res, iter->second);
return res;
}
int find(int x){//路径压缩
if (parent[x] == x) return x;
parent[x] = find(parent[x]);
return parent[x];
}
void unions(int x, int y){
x = find(x);
y = find(y);
if(x==y) return;
parent[y] = x;
}
};
从前往后
// 从前往后,主动去找在同一集合的元素,根节点为公因数
vector<bool> prime(maxNum+1,1);
unordered_set<int> s(nums.begin(),nums.end());
for (int i = 2; i <= maxNum; i++)//遍历所有公因数
if (prime[i]) {//减少重复查找
for (int j = i * 2; j <= maxNum; j += i) {
prime[j] = 0;
if (s.count(j)) parent[find(j)] = find(i);//合并集合(根节点)
}
}
2. 暴力建图(深度优先)
class Solution {
public:
int largestComponentSize(vector<int>& nums) {
vector<vector<int>> graph(nums.size());
//建立邻接表图
for(int i=0;i<nums.size();i++)
for(int j=i+1;j<nums.size();j++){
if(gcd(nums[i],nums[j])>1){
graph[i].push_back(j);
graph[j].push_back(i);
}
}
vector<bool> visit(nums.size());
int res = INT_MIN;
for(int i=0;i<nums.size();i++){
int count = 0;
dfs(i,graph,visit,count);
res = max(count,res);
}
return res;
}
void dfs(int i,vector<vector<int>>&graph,vector<bool>&visit,int&count){
if(visit[i]) return;
visit[i] = 1;
count++;
for(int j=0;j<graph[i].size();j++)
dfs(graph[i][j],graph,visit,count);
}
};