难度:简单
思路: 维护一个栈,遍历字符串的每一个字符,如果是左括号,压入栈中;如果是右括号,只有当它和栈顶的左括号相匹配时,原串才合法。如果当前的右括号和栈顶的左括号不匹配,返回False,如果匹配,将栈顶的左括号弹出,因为这个左括号找到了与其对应的右括号,对最终结果不再影响。持续这个操作,如果最后栈为空,那么说明所有的左括号都找到了与其对应的右括号,那么这个字符串为合法的,反之不合法。
代码:
class Solution:
def isValid(self, s: str) -> bool:
dic = {'{':'}','(':')','[':']','?':'?'}
st = ['?']
for c in s:
if c in dic:
st.append(c)
elif dic[st.pop()] != c:
return False
return len(st) == 1
首先创建一个字典dic,字典的键为左括号,字典的值为这个左括号所期待匹配的右括号。当遇到右括号时,用栈顶的左括号作为键查字典得到其期待的右括号,将这个两个右括号进行比较,如果相等,弹栈,不等,则返回False。最后判断栈是否为空,空则返回True,反之返回False。
上述代码中在栈底压入了一个哨兵'?',其作用是:减少不必的边界检查。如果不加这个哨兵,当遇到右括号时,我们必须将栈顶的左括号弹栈进行匹配,如果这时栈空,那么弹栈会引发异常。基础的解决办法是每次弹栈前都判断栈是否为空。更好的做法是增加一个哨兵'?',栈为空时,栈底也有一个'?',那么弹栈和右括号必不匹配,因此返回False,这样就不会导致弹空栈的问题,因此弹栈之前不会判断栈是否为空了,。算是一种巧妙地优化。
复杂度分析:由于只遍历一次字符串,且每次弹栈比较都是O(1)的,因此时间复制度为O(n),其中n为字符串长度。