题目
给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。
示例1
输入:["a==b","b!=a"]
输出:false
解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。
题解
并查集
- 构建并查集
- 第一次枚举,将相同的变量合并,使他们指向同一个节点
- 第二次枚举,找到不同相同的变量a,b的祖先节点,如果a,b祖先节点一样;返回false
代码
var equationsPossible = function (equations) {
// 构建集合
const list = Array(26)
.fill(0)
.map((v, i) => i);
// 第一次遍历
for (let i = 0; i < equations.length; i++) {
const a = equations[i][0];
const b = equations[i][3];
const s = equations[i][1];
// 将相同的数据合并在list中,相同的数据公用一个祖先
if (s === '=') {
// 相同,合并
merge(
a.charCodeAt() - 'a'.charCodeAt(),
b.charCodeAt() - 'a'.charCodeAt()
);
}
//console.log('list', list);
}
// 第二次遍历
for (let i = 0; i < equations.length; i++) {
const a = equations[i][0];
const b = equations[i][3];
const s = equations[i][1];
// 如果不同的两个变量
if (s === '!') {
//寻在不同变量的祖先节点
const x = loop(a.charCodeAt() - 'a'.charCodeAt());
const y = loop(b.charCodeAt() - 'a'.charCodeAt());
// 如果祖先相同,返回false
if (x === y) return false;
}
}
return true;
// 并查集中的并,将a并给b
function merge(a, b) {
const x = loop(a);
const y = loop(b);
list[x] = y;
}
// 递归查询祖先节点,也可以使用迭代
function loop(n) {
if (n === list[n]) return list[n];
return loop(list[n]);
// while(n !== list[n]){
// list[n] = list[list[n]]
// n = list[n]
// }
// return list[n]
}
};