題目描述
給定一個由表示變量之間關係的字符串方程組成的數組,每個字符串方程 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
示例 4:
輸入:["a==b","b!=c","c==a"]
輸出:false
示例 5:
輸入:["c==c","b==d","x!=z"]
輸出:true
提示:
1 <= equations.length <= 500
equations[i].length == 4
equations[i][0] 和 equations[i][3] 是小寫字母
equations[i][1] 要麼是 '=',要麼是 '!'
equations[i][2] 是 '='
解題思路
本題採用並查集的思想:(不太瞭解並查集的小夥伴可看【算法基礎】並查集的原理及使用)
- 第一遍循環,將
equations[i]
中等式都找出來,然後將等式左右兩邊的字母放入同一集合; - 第二遍循環,判斷
equations[i]
中若有不等式兩邊字母屬於同一集合,則返回false
,否則返回true
。
本題利用數組的方式存儲每個單詞的父親節點。
用find()
函數返回該字母的根結點。
若等式兩邊的數字相等,則讓左邊數字的根結點的父親節點指向右邊數字的根結點。
在find()
函數函數中:
- 若
return find(parent[index]);
此方法爲不壓縮路徑的方法 - 若
parent[index] = find(parent[index]);
再return parent[index];
此方法爲壓縮路徑的方法
壓縮路徑的方法在查找時較快,運行所需時間較少。
具體代碼
class Solution {
public:
//定義一個長度爲26的數組parent,用於存放父節點
int parent[26];
//查找根結點
int find(int index){
//根結點是自身
if(index == parent[index]) return index;
//如果不是的話則一直向上尋找根結點,同時壓縮路徑
parent[index] = find(parent[index]);
return parent[index];
//return find(parent[index]); 此方法爲不壓縮路徑的方法
}
//合併函數,將第一個數的根結點的父節點指向第二個數的根結點
void unite(int index1, int index2){
parent[find(index1)] = find(index2);
}
bool equationsPossible(vector<string>& equations) {
//開始時自己指向自己
for(int i = 0;i<26;i++) parent[i] = i;
//先循環一邊,將相同的添加到同一集合中
for(int i = 0;i<equations.size();i++){
if(equations[i][1] == '='){
int index1 = equations[i][0] - 'a';
int index2 = equations[i][3] - 'a';
unite(index1, index2);
}
}
//開始查找並判斷是否在同一集合
for(int i = 0;i<equations.size();i++){
if(equations[i][1] == '!'){
int index1 = equations[i][0] - 'a';
int index2 = equations[i][3] - 'a';
if(find(index1) == find(index2)) return false;
}
}
for(int i = 0; i<6;i++)cout<<parent[i]<<" ";
return true;
}
};