算法: 有效的括号

Posted on Sep 15, 2020

问题描述

给定一个只包括 '(', ')', '{', '}', '[', ']' 的字符串, 判断字符串是否有效.

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合.
  2. 左括号必须以正确的顺序闭合.

注意空字符串可被认为是有效字符串.

题目地址:https://leetcode-cn.com/problems/valid-parentheses/

(看了评论才知道是B站开发岗面试题)

示例

输入: "()"
输出: true

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

输入: "(]"
输出: false

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

输入: "{[]}"
输出: true

解答

思路一

class Solution:
    def isValid(self, s):
        while '{}' in s or '()' in s or '[]' in s:
            s = s.replace('{}', '')
            s = s.replace('[]', '')
            s = s.replace('()', '')
        return s == ''

对于正确的来说, 每次都能去掉一对括号, 最后就成了空.

思路二

其实这个题主要是考大家关于栈的应用

原理

  • 栈先入后出特点恰好与本题括号排序特点一致, 即若遇到左括号入栈, 遇到右括号时将对应栈顶左括号出栈, 则遍历完所有括号后 stack 仍然为空;

  • 建立哈希表dic构建左右括号对应关系:key 左括号, value 右括号;这样查询 2 个括号是否对应只需 $O(1)$ 时间复杂度;建立栈 stack, 遍历字符串s 并按照算法流程一一判断.

流程

如果 c 是左括号, 则入栈 push; 否则通过哈希表判断括号对应关系, 若 stack 栈顶出栈括号 stack.pop() 与当前遍历括号 c 不对应, 则提前返回 false.

提高算法效率

提前返回false
  • 边界问题栈 stack 为空: 此时stack.pop()操作会报错;因此, 我们采用一个取巧方法, 给 stack 赋初值 ? , 并在哈希表 dic 中建立 key: '?', value:'?'的对应关系予以配合. 此时当 stack 为空且 c 为右括号时, 可以正常提前返回 false

  • 字符串 s 以左括号结尾: 此情况下可以正常遍历完整个 s, 但 stack 中遗留未出栈的左括号;因此, 最后需返回 len(stack) == 1, 以判断是否是有效的括号组合.

时间复杂度

  • 时间复杂度 $O(N)$:正确的括号组合需要遍历 11 遍 s
  • 空间复杂度 $O(N)$:哈希表和栈使用线性的空间大小.

示意图

1600170005135

代码

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

原作者:Krahets