题目
https://leetcode-cn.com/problems/satisfiability-of-equality-equations/
并查集
由题可知等式关系具有传递性,==可以看作链接两个顶点的边,如果 a = = b , b = = c 那 么 a = = c a==b, b == c 那么 a == c a==b,b==c那么a==c所以相等的分量同属于一个连通分量,可以使用并查集来维护这种连通分量的关系。
- 首先遍历所有等式,将顶点合并构建并查集
- 再遍历所有不等式,通过并查集判断两个顶点是否连通,如果连通则产生矛盾,返回false。所有的不等式如果都没有矛盾产生则返回true
class Solution {
public boolean equationsPossible(String[] equations) {
// 只有小写字母,声明顶点个数为26的并查集
UnionFind unionFind = new UnionFind(26);
// 先将所有等式子合并,等式中的两个变量同属一个连通分量
for (String equation : equations) {
char[] charArray = equation.toCharArray();
if (charArray[1] == '=') {
int vertex1 = charArray[0] - 'a';
int vertex2 = charArray[3] - 'a';
unionFind.union(vertex1, vertex2);
}
}
// 遍历所有不等式判断顶点是否连通如果连通表示等式有矛盾返回false
for (String equation : equations) {
char[] charArray = equation.toCharArray();
if (charArray[1] == '!') {
int vertex1 = charArray[0] - 'a';
int vertex2 = charArray[3] - 'a';
if (unionFind.isConnected(vertex1, vertex2))
return false;
}
}
// 所有不等式都不连通则返回true
return true;
}
private class UnionFind {
// 下标为顶点值为指向的父节点
private int[] parent;
public UnionFind(int n) {
parent = new int[n];
// 初始化所有的顶点指向自己
for (int i = 0; i < n; i++) {
parent[i] = i;
}
}
// 路径压缩(隔代压缩)
public int find(int x) {
while (x != parent[x]) {
parent[x] = parent[parent[x]];
x = parent[x];
}
return x;
}
// 两个根节点相连,相当于合并
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
parent[rootX] = rootY;
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
}