题目
解题
- 本题就是那种分类的题目,按照变量值是否相等分成各个集合,每个集合中的变量值相互之间都是相等的。我们可以利用并查集来实现本题算法。
- 我们先遍历所有的式子,如果为相等的式子,那么我们就像式子两边的变量放入同一个集合中,当遍历结束之后,直接或间接相等的值的变量名都被分配到同一个集合中。
- 然后我们再遍历一遍,找出不相等的式子,如果式子左边两个值的变量名不在同一个集合,则说明这个式子成立,继续下一个式子。如果两个变量名在同一个集合,则说明式子关系出现矛盾,返回false。
- 至于怎样判断两个变量名是否在同一个集合中,我们就需要用到并查集的特性,在每一个集合中,我们在创建该集合时会出现一个代表。比如(按照下面代码画的示意图,加入集合的节点每次都是作为父节点加入):
在遍历一遍后,所有的变量名都在一个集合中,当再次遍历查到不相等的式子时,发现 f 和 e 在同一个集合中,说明关系出现矛盾,返回错误。
具体代码实现
class Solution {
public:
//查找该变量名所在集合的代表
int find(int index, vector<int> parent){
//如果变量名的父节点是它本身,则说明该变量名就是集合的代表
if(index == parent[index]){
return index;
}
parent[index] = find(parent[index],parent);
return parent[index];
}
bool equationsPossible(vector<string>& equations) {
vector<int> parent(26);//建立并查集,利用数组来构建
//初始时,所有的变量名的集合代表就是他自身
for(int i = 0; i < 26; i++){
parent[i] = i;
}
int len = equations.size();//记录有多少个式子
//第一遍遍历,找到相等关系的式子构建集合
for(int i = 0; i < len; i++){
if(equations[i][1] == '='){
int index1 = equations[i][0] - 'a';
int index2 = equations[i][3] - 'a';
//如果变量名相等,则将等式左边变量名所在集合的代表变成右边变量名所在集合的代表
parent[find(index1,parent)] = find(index2,parent);
}
}
//第二遍遍历,寻找是否有矛盾的关系式
for(int i = 0; i < len; i++){
if(equations[i][1] == '!'){
int index1 = equations[i][0] - 'a';
int index2 = equations[i][3] - 'a';
//如果左右两边的变量名的代表为同一个,则说明两个变量名在同一个集合
if(find(index1,parent) == find(index2,parent)){
return false;
}
}
}
return true;
}
};
总结
如果碰到类似本题需要将变量按照某种关系分类,并且验证某两个变量之间是否属于同一个关系时,可以利用并查集来解决!