64,082
社区成员
发帖
与我相关
我的任务
分享
990. 等式方程的可满足性
解题思路:
1. 建立一个容器,初始值为容器下标的自身
2. 遍历容器,把==号的元素放入并查集,每个元素的值为他能够推出的结果。
3. 我们需要通过递归来推出这一个结果,若一个元素的元素不是他自身,那么他已经在一个等式系统了。假设a==d,此时a和d连通,也相当于以a(在数组中映射为0)为下标的元素和d连通,那么我们只需要修改a为下标的元素到d的连通性就好了,如果a下标所指代的元素,其作为下标在数组中对应的值还不是他自己,那么继续递归。
class UnionFind {
public:
vector<int> hash;
UnionFind() {
hash.resize(26);
iota(hash.begin(), hash.end(), 0);
}
int find(int id) {
if(hash[id] == id) return id;
hash[id] = find(hash[id]);
return hash[id];
}
//在同一个等式系统中
void unite(int id1, int id2) {
hash[find(id1)] = find(id2);
}
};
class Solution {
public:
bool equationsPossible(vector<string>& equations) {
UnionFind uf;
for(auto it: equations) {
if(it[1] == '=') {
int id1 = it[0] - 'a';
int id2 = it[3] - 'a';
uf.unite(id1, id2);
}
}
for(auto it: equations) {
if(it[1] == '!') {
int id1 = it[0] - 'a';
int id2 = it[3] - 'a';
if(uf.find(id1) == uf.find(id2)) return false;
}
}
return true;
}
};
1319. 连通网络的操作次数
解题思路:
跟上一题差不多的思路。
1.将元素放入并查集,如果两个元素已经在并查集的话,那么边的数++
2.遍历得到连通块的个数
3.如果连通块的个数 - 1不大于多余边的数量的话,那么就是可以连接的。
class UnionFind {
public:
vector<int> hash;
UnionFind(int n) {
hash.resize(n);
iota(hash.begin(), hash.end(), 0);
}
int find(int index) {
if(index == hash[index]) return index; //该电脑目前还没有联通
hash[index] = find(hash[index]);
return hash[index];
}
bool unite(int index1, int index2) {
int id1 = find(index1);
int id2 = find(index2);
if(id1 == id2) return false;
hash[id1] = id2;
return true;
}
};
class Solution {
public:
int makeConnected(int n, vector<vector<int>>& connections) {
UnionFind uf(n);
int edge = 0;
int count = 0;
//构建并查集
for(auto it: connections) {
if(!uf.unite(it[0], it[1])) ++edge;
}
int arr[100010];
memset(arr, 0, sizeof(arr));
for(int i = 0; i < n; ++i) {
int setID = uf.find(i);
if(!arr[setID]) {
arr[setID] = 1;
++count;
}
}
cout << edge << " " << count;
if(edge >= count - 1) return count - 1;
else return -1;
}
};