20. 有效的括号

简单 含交互动画

学完这道你应该能: 说清它为什么用「栈」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

题目描述

判断括号串是否正确闭合。每个左括号都要有对应的右括号,且顺序正确。

s = "([])"
输出 = true

思路解析

遇到左括号就压进栈;遇到右括号,就看栈顶的左括号能不能和它配成一对——能配就弹出栈顶,不能配就说明不合法。

准备:上面是要处理的字符串,下面是我们的栈。开始逐个字符处理。

第 0 个:'(':'(' 是左括号,压入栈。栈:[ ( ]

第 1 个:'[':'[' 也是左括号,压入栈。栈:[ (, [ ],栈顶是 '['。

第 2 个:']':']' 是右括号。看栈顶是 '[',正好是一对!可以把栈顶弹出去。

第 2 个:弹出:配对成功,弹出栈顶 '['。栈剩下:[ ( ]。

第 3 个:')':')' 是右括号。栈顶是 '(',又是一对!弹出。

第 3 个:弹出:弹出 '(',栈又空了。

结束:字符串走完,栈正好空了——说明每个左括号都找到了对应的右括号,返回 true

两种情况:① 右括号来了但栈顶配不上;② 字符串结束时栈还没空(有左括号没人配)。来看个反例。

反例 "(]" · '(':处理 "(]":先把 '(' 压入栈。

反例 · ']':遇到 ']',可栈顶是 '(',对不上号——立刻返回 false

凡是「最近出现的要最先被匹配/抵消」的问题,都该想到栈:逆波兰表达式、字符串解码、消消乐式的相邻消除……

参考代码(Python)

Python
1def isValid(self, s):
2    if len(s) % 2 == 1: return False  # 奇数个一定不合法
3    stack = list()
4    for c in s:
5        if c in class="cl-str">"([{":            # 左括号入栈
6            stack.append(c)
7        else:                     # 右括号
8            if not stack: return False  # 栈空,没人配
9            top = stack[-1]       # 取栈顶
10            if (top==class="cl-str">"(" and c==class="cl-str">")") or \
11               (top==class="cl-str">"[" and c==class="cl-str">"]") or \
12               (top==class="cl-str">"{" and c==class="cl-str">"}"):
13                stack.pop()       # 配对成功,弹出
14            else: return False    # 配不上,不合法
15    return not stack              # 栈空才合法

复杂度分析

  • 时间复杂度:O(n) —— 每个字符进出栈各一次
  • 空间复杂度:O(n) —— 最坏全是左括号,全进栈

套路模板

左括号进栈、右括号找栈顶配对。最近进来的最先被处理——这就是栈。

Python
1# 配对 / 相邻抵消骨架
2stack = []
3for c in s:
4    if 是左括号(c): stack.append(c)
5    else:
6        if not stack: return False
7        if 配对(stack[-1], c): stack.pop()
8        else: return False
9return not stack

易错点

  • 右括号不先判栈空就取 stack[-1] → ✅ 先 if not stack: return False(像 "]" 开头时栈是空的,直接取会报错)
  • 循环结束直接 return True → ✅ return not stack(像 "(" 结束时栈还非空,应是 False)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →704. 二分查找 ← 返回题库