前两天困难难度的题把我都做到自闭了,导致最后根本就不想写题解(也写不出来)。今天终于见到了一个看起来还能做的题,心里突然感觉有了希望,于是乎在尝试三种不同思路、大改代码几次后终于做出来了……
先上题目:
最开始我想到的办法就是分块记录等式和不等式,把相等的放在一个组,不等的分开放在不同的组,但是越写越觉得不对劲,因为这样根本没法进行判断,在逻辑上就行不通。于是乎半个小时过去了。
然后我又想了一个办法,就是先对所有式子进行排序,等式在前先处理,不等式后处理。然后把等式的字母放在一个集合中,不等式的字母先拿到等式字母的集合中来看看在不在,在的话返回False,不在的话放在另一个集合中。这种方法看起来似乎行得通,但是现实又给了我一个暴击,因为很容易就能找到反例。
现在以其中两个测试用例来进行说明:
这种方法不行,那应该怎么解决呢?我想了想,这种方法的问题主要出在把所有等式字母混在一起了,如果能把这些字母按照等式连接的情况分好组,那不就可以解决了嘛?而且回看处理过程,其实不等式的字母可以不加入到集合中。
因此我认为可以在上述方法的基础上进行以下修改:
①把等式和不等式分离,先处理等式构造可以连接的set list,再处理不等式
②等式形成的set list需要进行合并处理,最后输出一个组内元素两两不相交的set list
③对不等式的两端元素放到set list中进行判定,如果在同一个set中则直接返回False,否则跳过
以一个例子来说明为什么需要合并:
有了思路后,代码就很简单啦!代码如下所示:
class Solution:
def equationsPossible(self, equations: List[str]) -> bool:
#以下两个列表分别记录等式和不等式
equal = []
unequal = []
for i in range(len(equations)):
if equations[i][1] == "=":
equal.append(equations[i])
else:
unequal.append(equations[i])
record = []
#首先把等式所有可能的情况加进去集合中
for i in range(len(equal)):
signal = 0
for j in range(len(record)):
if equal[i][0] in record[j] or equal[i][3] in record[j]:
record[j].add(equal[i][0])
record[j].add(equal[i][3])
signal = 1
break
if signal == 0:
record.append(set([equal[i][0], equal[i][3]]))
#进行减少集合数量的操作,把并集不为空的集合合并,使得最后输出的集合钟的元素两两不相交
while True:
signal = 0
for i in range(len(record)-1):
for j in range(i + 1, len(record)):
#如果相交,就改前面那个集合,然后删掉后面的那个集合,跳出来重新循环(因为记录集合的列表长度变了)
if not set.isdisjoint(record[i], record[j]):
record[i] = set.union(record[i], record[j])
record.remove(record[j])
signal = 1
break
if signal == 1:
break
#如果记录集合的列表没有修改过,说明列表内的集合两两不相交,跳出循环
if signal == 0:
break
#对不等式进行判断
for i in range(len(unequal)):
#如果有两边相等的,直接False
if unequal[i][0] == unequal[i][3]:
return False
#看两边的元素是否在同一个集合中,在就返回False
for j in range(len(record)):
if unequal[i][0] in record[j] and unequal[i][3] in record[j]:
return False
return True
终于,在被困难题目虐了两天之后,我在早上就解好了题,实在是太感动了,虽然效率不咋地😭