给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 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:最原始的想法。最开始的想法是,里面有等式和不等式,根据等式的连等式性质,即a=b, b=c, 则a=c。可以将所给的链表分成两部分,一部分是全部相等的等式组成的列表same,另外一个是不等列表。
对于相等的列表来说,全部是相等关系,比如 a=b, b = c, d=e ,e=a, 可以将每个字符等价于与其相等的最小字符,即
zifu[a] = a, zifu[b] =a, zifu[c] = zifu[ zifu[b] ] =a,
zifu[ d ] = zifu[ e ] = d,
然后因为最后 e = a,我们要把 zifu[d] 和 zifu[e] 归到a上,也就是 zifu[d] = zifu[e] = a, 这样就可以做到标记,标记每个字母与其相等的最小字母的对应关系。(当然,每次遇到一个等式,直接将整个列表的字母替换一遍也可以,即每次和a相等的字符都变成a,全部替换,但是这样算法遍历就是O(n^2), 比上面标记慢)
将所有等式的对应关系搞定之后,就可以看不等式了。将不等式的每个字母找到其最小的相等的字母,如果两个字母为同一个字母,应该是相等,但这时是不等式,故错误。
思路2:整理一下上面思路1的问题,就会发现这是一个并查集问题,先处理相同的元素,将所有的一样的元素归并到一个爸爸的名下,然后对于不等式来说,每次的两个元素找各自的爸爸,如果两个爸爸一样的话,说明两个其实是相等的。这样就报错了
思路1:最原始的想法
class Solution:
def swap(self,a,b):
if(a> b): return b,a
else: return a,b
def equationsPossible(self, equations: List[str]) -> bool:
same = []
no_same = []
for i in equations:
if('!' in i): no_same.append(i)
else: same.append(i)
zifu = {}
for i in range(0,len(same)):
line = same[i]
t1 = line[0]
t2 = line[-1]
if(i == 0):
t1,t2 = self.swap(t1,t2)
zifu[t2] = t1
zifu[t1] = t1
else:
t1,t2 = self.swap(t1,t2)
if(t1 in zifu.keys() and t2 in zifu.keys()):
ttt = min(zifu[t1],zifu[t2])
old_t1 , old_t2 = zifu[t1],zifu[t2]
zifu[t1] = ttt
zifu[t2] = ttt
for t in zifu:
if(zifu[t]==old_t1 or zifu[t]==old_t2):zifu[t]= ttt#zifu[t1]
elif(t1 in zifu.keys() and t2 not in zifu.keys()):
zifu[t2] = zifu[t1]
elif(t1 not in zifu.keys() and t2 in zifu.keys()):
zifu[t1] = zifu[t2]
else:
zifu[t1] = t1
zifu[t2] = t1
for i in range(0,len(no_same)):
line = no_same[i]
t1 = line[0]
t2 = line[-1]
if(t1 in zifu.keys()): t1 = zifu[t1]
if(t2 in zifu.keys()): t2 = zifu[t2]
if(t1 == t2):return False
return True
思路2:并查集
class Solution:
class UnionFind():
def __init__(self):
self.parent = list(range(26))
def find(self,x):
if(x == self.parent[x]): return x
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def unino(self,x,y):
self.parent[self.find(x)] = self.find(y)
def equationsPossible(self, equations: List[str]) -> bool:
t = Solution.UnionFind()
for line in equations:
if(line[1]=='='):
x = ord(line[0]) - ord('a')
y = ord(line[-1]) - ord('a')
t.unino(x,y)
for line in equations:
if(line[1]=='='):continue
x = ord(line[0])-ord('a')
y = ord(line[-1])-ord('a')
if(t.find(x)==t.find(y)):
return False
return True