1 并查集
- 将等式左右两侧的字母(节点)在图中进行连接
- 将不等式左右两侧的字母在图中检查连通性,若连通,则式子冲突,否则满足
class UnionFind {
public:
int count; // 连通分量
vector<int> parent, size;
UnionFind(int n) {
count = n; // 初始每个节点是1课树
parent.resize(n); // 父节点
size.resize(n); // 每个节点为根的树的节点数量
for (int i = 0; i < n; i++) {
parent[i] = i; // 初始每个节点的父节点是自己
size[i] = 1; // 只有自己,因此数量为1
}
}
// 合并a和b节点(合并两棵树)
void unite(int a, int b) {
int rootA = find_root(a);
int rootB = find_root(b);
if (rootA == rootB) return;
// 1.若A树节点数 < B树,则把A接到B下,并更新B树的节点数目
if (size[rootA] < size[rootB]) {
parent[rootA] = rootB;
size[rootB] += size[rootA];
} else {
parent[rootB] = rootA;
size[rootA] += size[rootB];
}
// 合并2棵树后连通分量-1
count--;
}
// 检查a和b点连通性
bool connected(int a, int b) {
int rootA = find_root(a);
int rootB = find_root(b);
return rootA == rootB;
}
// 返回node节点的根节点
int find_root(int node) {
while (parent[node] != node) {
parent[node] = parent[parent[node]]; // 2.路径压缩
node = parent[node];
}
return node;
}
};
class Solution {
public:
bool equationsPossible(vector<string>& equations) {
int size = equations.size();
UnionFind uf(26); // 26个字母,作为26个节点
// 先对等式进行建树
for (int i = 0; i < size; i++) {
if (equations[i][1] == '=')
uf.unite(equations[i][0] - 'a', equations[i][3] - 'a');
}
// 不等式拿来检查连通性,若连通,则等式不成立,反之成立
for (int i = 0; i < size; i++) {
if (equations[i][1] == '!')
if (uf.connected(equations[i][0] - 'a', equations[i][3] - 'a')) return false;
}
return true;
}
};