目录
一,题目描述
英文描述
You are given an array of strings equations that represent relationships between variables where each string equations[i] is of length 4 and takes one of two different forms: "xi==yi" or "xi!=yi".Here, xi and yi are lowercase letters (not necessarily different) that represent one-letter variable names.
Return true if it is possible to assign integers to variable names so as to satisfy all the given equations, or false otherwise.
中文描述
给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。
示例与说明
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/satisfiability-of-equality-equations
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二,解题思路
第一步,遍历所有等式,提取所有出现过的字符串变量,存放到set中去重;
第二步,根据第一步中提取出的变量,初始化并查集;
第三步,遍历所有含"=="的等式,完善并查集的联通关系;
第四步,遍历所有含"!="的等式,判断联通关系是否有冲突,有则返回false;
第五步,返回true。
注意:并查集应用中很容易出现的一种错误是,路径未完全压缩(同一棵树上节点的father不一定完全相同),然后直接用father[a] == father[b]来判断两节点是否联通。。。
解决方法如下:
三,AC代码
Java
class Solution {
public boolean equationsPossible(String[] equations) {
Map<String, String> father = new HashMap<>();
Set<String> record = new HashSet<>();
// 提取字符串变量
for (int i = 0; i < equations.length; i++) {
String s1 = equations[i].substring(0, 1);// 提取字符串[0,1)
String s2 = equations[i].substring(3, 4);
record.add(s1);
record.add(s2);
}
// 初始化并查集
for (String s : record) {
father.put(s, s);
}
// 建立联通关系
for (int i = 0; i < equations.length; i++) {
if ("=".equals(equations[i].substring(1, 2))) {
String s1 = equations[i].substring(0, 1);
String s2 = equations[i].substring(3, 4);
unionSet(father, s1, s2);
}
}
for (int i = 0; i < equations.length; i++) {
if ("!".equals(equations[i].substring(1, 2))) {
String s1 = equations[i].substring(0, 1);
String s2 = equations[i].substring(3, 4);
String S1 = findFather(father, s1);// !!!这里需要重新对树进行路径压缩,确保树上所有子节点的father唯一
String S2 = findFather(father, s2);// !!!这里需要重新对树进行路径压缩,确保树上所有子节点的father唯一
if (S1.equals(S2)) return false;
}
}
return true;
}
// 执行findather的同时会将树上的节点进行路径压缩
public String findFather(Map<String, String> father, String s) {
if (!father.get(s).equals(s)) {
father.put(s, findFather(father, father.get(s)));// 直接put新的value会覆盖原先的
}
return father.get(s);
}
public void unionSet(Map<String, String> father, String a, String b) {
String A = findFather(father, a);
String B = findFather(father, b);
if (!A.equals(B)) {
father.put(A, B);
}
}
}
四,解题过程
第一博
字符串处理稍微有点麻烦,但是并查集的思路还是比较清晰的。