Leetcode 990. 等式方程的可满足性

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值