判断equations里面的条件是不是都满足。
思路:
Union Find
可以这样想,先通过"==“的等式把值相同的字母聚类,一个类别是一个值,
然后再通过”!="的不等式来验证值是不是有矛盾,有矛盾就返回false.
聚类(union):
首先根据"=="的等式建立union,
每个union有一个root,也就是说找到union里面任何一个点最终都会找到root。
每个点的root是它自己。
遍历"=="关系,当一条边右端点的root是它自己时,更新root为左端点。把左端点当作右端点的root。也可以反过来,把右端点当成root。
当右端点的root不是它自己时,说明它连接的有另一个节点,顺藤摸瓜一直摸到它的root。
验证(find):
union建立好之后,开始find
遍历"!="的不等式,找到左右两边点的root,它们的root相同时,发生矛盾,返回false
本来union的过程需要把点都连接到root上面,
比如:1->2->3->4, 要找4的root需要往上找好几层才能找到1,一般在union的过程中会把3,4直接连接到1.
这里做了简易union,2层2层往上连接,起了查找时间log2的作用。
总结一下,这种需要聚成几类后面方便验证或查找的,要想到union-find
public boolean equationsPossible(String[] equations) {
int[] root = new int[26];
for(int i = 0; i < 26; i++) {
root[i] = i;
}
//先处理“==”
for(String equ : equations) {
if(equ.charAt(1) == '!') continue;
int idx1 = equ.charAt(0) - 'a';
int idx2 = equ.charAt(3) - 'a';
//"=="左边的root定义为"=="右边的root
root[find(root, idx1)] = find(root, idx2);
}
//处理"!="
for(String equ : equations) {
if(equ.charAt(1) == '=') continue;
int idx1 = equ.charAt(0) - 'a';
int idx2 = equ.charAt(3) - 'a';
//"=="左边的root定义为"=="右边的root
if(find(root, idx1) == find(root, idx2)) return false;
}
return true;
}
int find(int[] root, int idx) {
int parent = idx;
while(root[parent] != parent) {
parent = root[parent];
root[parent] = root[root[parent]]; //简易union
}
return parent;
}