给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。
示例 1:
输入: ["a==b","b!=a"]
输出: false
解释: 如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。
示例 2:
输入: ["b==a","a==b"]
输出: true
解释: 我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。
示例 3:
输入: ["a==b","b==c","a==c"]
输出: true
思路
==即建立两个变量的关系,!=即使认为两个变量没有关系,遍历所有==建立并查集,然后遍历!=利用isConnect判断是否不在一个连通分量中。本实现用了路径压缩,树高小的合并到树高高的里,类似平衡树思想,避免退化成链表
class Solution {
public boolean equationsPossible(String[] equations) {
//==即使建立两个变量的关系,!=即使破坏两个变量的关系,最终如果联通为一个联通量即返回true
//等价替换一下,遍历所有等于的公式建立并查集,然后遍历!=看是否属于两个连通分量,
Set<Character> nodes = new HashSet<>();
List<String> equals = new ArrayList<>();
List<String> nonEquals = new ArrayList<>();
UnionFind<Character> unionFind = new UnionFind<>();
for (String e : equations) {
unionFind.add(e.charAt(0));
unionFind.add(e.charAt(3));
if (e.charAt(1) == '!'){
nonEquals.add(e);
}else{
equals.add(e);
}
}
int count = unionFind.getCount();
for (int i = 0; i < equals.size(); i++) {
unionFind.union(equals.get(i).charAt(0), equals.get(i).charAt(3));
}
for (int i = 0; i < nonEquals.size(); i++) {
if(unionFind.isConnect(nonEquals.get(i).charAt(0), nonEquals.get(i).charAt(3))){
return false;
}
}
return true;
}
public class UnionFind<T>{
Map<T, T> parents;
Map<T, Integer> rank;
int count;
public UnionFind(){
parents = new HashMap<>();
rank = new HashMap<>();
}
public int getCount(){
return count;
}
// 初始化
public void add(T element){
if (!parents.containsKey(element)) {
parents.put(element, element); // 每个元素的父节点初始化为自己
rank.put(element, 1); // 初始秩为0
count++; // 新增一个元素即增加一个联通分量
}
}
//返回根节点
public T find(T element){
if (!parents.containsKey(element)){
return null;
}
while (!parents.get(element).equals(element)){
element = parents.get(element);
}
return element;
}
public boolean isConnect(T element1, T element2){
return find(element1).equals(find(element2));
}
public void union(T element1, T element2){
T t1 = find(element1);
T t2 = find(element2);
if (t1.equals(t2)){
return;
}
if (rank.get(t1).equals(rank.get(t2))){
parents.put(t1, t2);
rank.put(t2, rank.get(t2) + 1);
}else if (rank.get(t1).compareTo(rank.get(t2)) < 0){
parents.put(t1, t2);
}else{
parents.put(t2, t1);
}
count--;
}
}
}