Vvvrf / DSA.log← 返回全部笔记
LEETCODE 020Easy

有效的括号

括号匹配的本质是“最近打开的必须最先关闭”,这正好是栈的定义。

问题拆解

给定一个只含 ()[]{} 的字符串,要判断括号是否正确闭合。合法有两个条件:类型要配对,顺序也要对。像 ([)] 三种括号数量都对,却因为交叉嵌套而非法。

我一开始想过“数一数每种括号左右是否相等”,但 ([)] 立刻推翻了这个想法——数量对不代表顺序对。真正的关键是:每遇到一个右括号,它必须闭合的是当前还没关闭的、离它最近的那个左括号

“最近打开的必须最先关闭”,这句话本身就是栈的先进后出(LIFO)。

用栈匹配最近的左括号

把左括号一路压栈;遇到右括号时,栈顶就是“最近未闭合的左括号”,检查它们是否成对即可。我用一个字典把右括号映射到它期待的左括号,判断时更直接。

def isValid(s: str) -> bool:
    pairs = {")": "(", "]": "[", "}": "{"}
    stack = []

    for ch in s:
        if ch not in pairs:
            stack.append(ch)
        elif not stack or stack.pop() != pairs[ch]:
            return False

    return not stack

两个容易漏的边界:遇到右括号但栈是空的(没有左括号与之配对),直接判非法;遍历结束后栈必须为空,否则说明还有左括号没被关闭,比如 (((

复杂度

指标 复杂度 原因
时间 O(n) 每个字符进出栈各一次
空间 O(n) 最坏情况全是左括号,全部压栈

可以迁移的模式

  • 需要处理“嵌套”“配对”“就近匹配”的结构;
  • 当前的决策只依赖“最近一次未完成的操作”;
  • 逆序回收:后进来的先被处理掉。

看到“成对”“嵌套”“最近的一个”,先想想能不能用栈把“最近”这件事管起来。