题目简介:
给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i]
的长度为 4
,并采用两种不同的形式之一:"a==b"
或 "a!=b"
。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true
,否则返回 false
。
示例 1:
1 2 3
| 输入:["a==b","b!=a"] 输出:false 解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。
|
示例 2:
1 2 3
| 输出:["b==a","a==b"] 输入:true 解释:我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。
|
示例 3:
1 2
| 输入:["a==b","b==c","a==c"] 输出:true
|
示例 4:
1 2
| 输入:["a==b","b!=c","c==a"] 输出:false
|
示例 5:
1 2
| 输入:["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]
是 '='
思路:
第一次做并查集的题目,看了两篇比较有意思的博客,把并查集初步的搞懂了。
首先有26个字母,在没有等式限制时,它们自成一派,每个字母都是自己门派的掌门人。
当有等式限制时,若两者相等,则说明两个门派需要合并成一个门派,谁是新的掌门人并不重要。
若两者不能相等时,则寻找各自门派的掌门人,若两者的掌门人是一样的,说明不符合题意,返回false
即可。
在寻找掌门人时,可以使用路径压缩,简单点来说,若一开始从掌门人到字母一共有好几个阶级,这样子找掌门人时便要一层一层的向上,比较浪费时间。但是我们关心的只有门派掌门人是谁,和你中间的人是谁并没有关系,所以在寻找的过程中,我们可以将过程中遇到的人都直接隶属于掌门麾下,这样子寻找掌门人的速度就快很多了。
大致上就像这样:
tips:
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| class Solution { public:
vector<int> father;
int find(int x){
if(father[x] == x) return x; else{
father[x] = find(father[x]); return father[x]; } }
bool equationsPossible(vector<string>& equations) {
father.resize(26);
for(int i = 0; i < 26; i++){
father[i] = i; }
for(int i = 0; i < equations.size(); i++){
if(equations[i][1] == '='){
int father1 = find(equations[i][0] - 'a'); int father2 = find(equations[i][3] - 'a');
if(father1 != father2){
father[father1] = father2; } } }
for(int i = 0; i < equations.size(); i++){
if(equations[i][1] == '!'){
int father1 = find(equations[i][0] - 'a'); int father2 = find(equations[i][3] - 'a');
if(father1 == father2) return false; } }
return true;
} };
|