【栈与队列】力扣20:有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
示例1:

输入:s = "()[]{}"
输出:true

示例2:

输入:s = "([)]"
输出:false


  1. 括号匹配是典型的使用后进先出的栈来解决的问题,既可以满足匹配,又可以满足括号闭合的正确顺序。
    从左往右遍历,每当遇到左括号便放入栈内,遇到右括号则判断其和栈顶的括号是否是统一类型,是则从栈内取出左括号,否则说明字符串不合法。
    为了快速判断括号的类型,可以使用哈希表存储每一种括号实现快速配对(而不是写一堆elif)。哈希表(字典)的【键】为右括号,【值】为相同类型的左括号。
    在遍历结束后,如果栈中没有左括号,说明字符串 s 中的所有左括号闭合,返回 True,否则返回 False。
    提前返回False:注意到有效字符串的长度一定为偶数,因此如果字符串的长度为奇数,可以直接返回 False,省去后续的遍历判断过程。
class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2 == 1:
            return False
        pairs = {')': '(', '}': '{', ']': '['} # 哈希表的key是右括号,value是左括号
        stack = [] # 定义栈
        for char in s:
            if char in pairs:
                if not stack or stack[-1] != pairs[char]: # 栈为空or栈顶元素不属于六种符号的情况
                    return False
                stack.pop() # else的情况
            else:
                stack.append(char)
        return not stack # 如果括号全部匹配完成并被弹出,最后的栈就是空栈,返回True;只要栈中还有元素,说明没有完全匹配,那么返回False

另一种代码,两个if位置不一样

class Solution:
    def isValid(self, s: str) -> bool:
        pairs = {')': '(', '}': '{', ']': '['} # 哈希表的key是右括号,value是左括号
        stack = [] # 定义栈
        for char in s:
            if stack and char in pairs: # 栈不为空 且 字符串的元素属于6种规定符号,才进行匹配
                if stack[-1] == pairs[char]: # 栈顶是左括号 且 与整个char的value相等,就可以弹出
                    stack.pop()
                else: # 栈顶没有匹配的元素则直接返回False
                    return False
            else: # 栈为空 or 元素不属于6种规定符号,入栈
                stack.append(char)
        return not stack

小技巧解决边界问题:

  • 栈 stack 为空:此时 stack.pop() 操作会报错;因此,采用一个取巧方法,给 stack 赋初值 ? ,并在哈希表 pairs 中建立 key: ?,value: ? 的对应关系予以配合。此时当 stack 为空且 char 为右括号时,可以正常提前返回 false;
  • 字符串 s 以左括号结尾:此情况下可以正常遍历完整个 s,但 stack 中遗留未出栈的左括号;因此,最后需返回 len(stack) == 1,以判断是否是有效的括号组合。
class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'{': '}',  '[': ']', '(': ')', '?': '?'}
        stack = ['?'] # 初始化栈
        for c in s:
            if c in dic: stack.append(c)
            elif dic[stack.pop()] != c: return False
        return len(stack) == 1 # 栈有初始值?,所以如果匹配全部成功,最后应当剩一个值

作者:jyd
链接:https://leetcode.cn/problems/valid-parentheses/solution/valid-parentheses-fu-zhu-zhan-fa-by-jin407891080/

时间复杂度:O(n),其中 n 是字符串 s 的长度。遍历了一遍字符串。
空间复杂度:O(n + ∣Σ∣),其中 Σ 表示字符集,本题中字符串只包含 6 种括号,∣Σ∣ = 6。栈中的字符数量为 O(n),而哈希表使用的空间为 O(∣Σ∣),相加即可得到总空间复杂度。最坏情况下,假如输入是 (((((((,栈的大小将是输入字符串的长度。

  1. 消消乐 - 字符串替换
@ Java

class Solution {
    public boolean isValid(String s) {
        while(true){
            int l=s.length();
            s=s.replace("()","");
            s=s.replace("{}","");
            s=s.replace("[]","");
            if(s.length()==l){return l==0;}
        }
    }
}

写出的python版本超出时间限制

class Solution:
    def isValid(self, s: str) -> bool:
        while True:
            l = len(s)
            s = s.replace('()', '')
            s = s.replace('[]', '')
            s = s.replace('{}', '')
            if len(s) == 1:
                return l == 0
  1. ASCⅡ码
@ C++

class Solution {
public:
    bool isValid(string s) {
        if(s == ""){
            return true;
        }
        vector<char> stack;
        stack.push_back(s[0]);
        for(int i=1; i<s.size(); i++){
            if(stack.empty() == true){
                stack.push_back(s[i]);
            }else if(s[i] - stack.back() == 1 || s[i] - stack.back() == 2){
                stack.pop_back();
            } else {
                stack.push_back(s[i]);
            }
        }

        return stack.empty();
    }
};
posted @ 2022-05-20 10:02  Vonos  阅读(60)  评论(0)    收藏  举报