最大公约数遍历
两个数的最大公因数大于一时,表示两个数连通
给一个数组,判断该数组是否全连通
1. 并查集
通过质因数间接合并数组中所有数
#define limit (int)1e5
vector<int> fac[limit + 10];//建立一个二维数组存储每一个数的全部质因数
// 全局预处理每个数的质因数,这里只处理一次,后面还能用到其他判例
int init = []() {
for (int i = 2; i <= limit; i++)
if (fac[i].empty()) //表示该数为质因数
for (int j = i; j <= limit; j += i) //给它的所有倍数添加该质因数
fac[j].push_back(i);
return 0;
}();
class Solution {
public:
vector<int> parent;
bool canTraverseAllPairs(vector<int>& nums) {
int n = nums.size();
int mx = *max_element(nums.begin(),nums.end());//限制一下可能得质因数范围,优化
// 初始化并查集,应该包括数组所有数,以及可能的全部质因数,前n位表示数组数的集合,后mx位表示质因数集合
//通过质因数集合来合并数组集合
parent.resize(n+mx+1);
iota(parent.begin(),parent.end(),0);
// 对每个 nums[i],向它们的质因数连边
for (int i = 0; i < n; i++) //对于数组每一个数
for (int p : fac[nums[i]]) { //列举它的全部质因数
unions(i,n+p);
}
// 检查是否所有位置点都在同一连通块内
unordered_set<int> st;
for (int i = 0; i < n; i++) st.insert(find(i));
return st.size() == 1;
}
int find(int i){ //寻找集合首索引,即集合的唯一标识符
if (parent[i] != i) parent[i] = find(parent[i]); //如果自己不是,递归寻找且更新索引
return parent[i];
}
void unions(int i ,int j){
parent[find(i)] = parent[find(j)];
}
};