LeetCode详解系列的总目录(持续更新中):
LeetCode详解之如何一步步优化到最佳解法:前100题目录(更新中...)-CSDN博客
LeetCode详解系列的上一题链接:
LeetCode详解之如何一步步优化到最佳解法:14. 最长公共前缀_leetcode 14-CSDN博客
目录
20. 有效的括号
本题题目链接:20. 有效的括号 - 力扣(LeetCode)
解法1:暴力解法
解法1思路:
从题目中,我们看出来,总共有3对括号,这种mapping关系我们可以用字典来存储,方便我们用O(1)的复杂度来查询。并且,对于每一个左括号,一方面,不一定有对应的右括号与之配对;另一方面,即使有这样的右括号,很大概率这个右括号不是字符串中的下一个字符。因此,我们需要有一个地方来存储还没有配对的括号,我们可以使用一个列表来存储这些信息。接着,我们开始遍历输入的字符串。
对于每一个字符,假如当前列表为空的话,我们需要判断这个字符对应的括号是左括号,还是右括号,因为输入的字符串有效的条件之一为“每个右括号都有一个对应的相同类型的左括号”,那么,如果当前的括号是右括号的话,我们就可以直接判断字符串不是有效的(因为列表为空,前面没有与之配对的左括号);如果当前的括号是左括号,我们就将其存储到列表中。
如果当前列表不为空的话,若当前的括号为右括号,我们需要判断列表中最后一个括号是不是和这个右括号是配对的,如果是的话,则配对成功,移除列表中最后一个括号;否则,输入的字符串不是有效的(因为当前的这个右括号没有与之配对的左括号,题目中指出字符串有效的条件之一为“左括号必须以正确的顺序闭合”)。若当前括号为左括号,则将这个括号存到列表中。
等遍历完字符串后,假如列表是非空的,说明还有没配对的括号,输入的字符串不是有效的;否则,输入的字符串是有效的。具体的代码如下所示:
代码:
class Solution:
def isValid(self, s: str) -> bool:
store = []
mapping = {
")": "(",
"}": "{",
"]": "["
}
for kuohao in s:
if not store:
if kuohao == ")" or kuohao == "}" or kuohao == "]":
return False
store.append(kuohao)
else:
if kuohao in mapping.keys():
if store[-1] != mapping[kuohao]:
return False
else:
store.pop()
else:
store.append(kuohao)
if store:
return False
else:
return True
解法性能:
优化思路:
在上面的代码中,我们发现,在遍历字符串时,不论当前列表是空,还是非空,我们都是对如果当前括号是右括号的情况进行判断处理,而对当前括号是左括号的情况,则直接放进列表中。那么,我们是不是可以将操作进行合并,先处理右括号和左括号的情况。如果是右括号的话,再处理列表是空,还是非空的情况。优化后的代码如下所示:
解法2:最终版
代码:
class Solution:
def isValid(self, s: str) -> bool:
store = []
mapping = {
")": "(",
"}": "{",
"]": "["
}
for kuohao in s:
if kuohao == ")" or kuohao == "}" or kuohao == "]":
if not store:
return False
else:
if store[-1] != mapping[kuohao]:
return False
else:
store.pop()
else:
store.append(kuohao)
if store:
return False
else:
return True
解法性能:
解法分析:
对比“解法2”和“解法1”的代码,我们可以发现,优化后的代码更加紧凑,逻辑更加清晰。代码紧凑,可以减少内存的消耗,因此,优化了这个指标。