20. 有效的括号(简单)
Blind 75 › 20. 有效的括号(简单) (第 16 章)
题目
给定一个只由 ( ) { } [ ] 这六种字符组成的字符串 s,判断它是不是「合法括号串」。
合法需要同时满足:
- 每个左括号
(、{、[都必须用同类型的右括号闭合; - 闭合顺序不能交叉:先出现的左括号必须后闭合;
- 每个右括号之前,都要有对应的同类型左括号。
换句话说:扫描时遇到一个右括号,它必须能马上和「最近一个还没闭合的左括号」配对,配不上就不合法。
自造示例:
| s | 结果 | 一句话原因 |
|---|---|---|
"{[()]}" | true | 内层 () 先合,再依次合 []、{} |
"[]({})" | true | 两段独立分组,各自配对正确且互不交叉 |
"([)]" | false | 括号交叉:( 还没闭合就来了错类型的 ) |
")(" | false | 右括号先出现,前面没有可配对左括号 |
"((()" | false | 扫描结束后仍有左括号未闭合 |
约束:1 ≤ s.length ≤ 104;s 仅由上述六种括号字符组成。
思路
一句话:遇到左括号就存起来,遇到右括号就检查「最近存进去的那个」是不是同类型。
最直白的想法是「消消乐」:反复删除相邻且同类型的闭合对 "()"、"[]"、"{}",直到不能再删;如果最后删空了,就说明合法。
例如 "{[()]}":先删 "()" 得 "{[]}",再删 "[]" 得 "{}",最后删 "{}" 得空串,返回 true。
这个方法直观又正确,但每一轮都要从头扫一遍;像 "((((...))))" 这种深嵌套串,每轮只能从最中间拆掉一层,最坏要扫 O(n) 轮,总时间退化成 O(n²)。
关键观察:遇到一个右括号时,它能不能闭合,只取决于「最近一个还没闭合的左括号」是不是同类型。这个“最近还没闭合、先来后走”的结构,正是后进先出——和「栈」天然匹配。
于是把扫描过程变成:左括号入栈;右括号和栈顶核对、配对成功就出栈;任何一步栈空或类型不匹配直接判 false;最后栈空才合法。
解法
用一个栈存放「尚未闭合的左括号」,栈顶永远是当前最内层的那个。
- 建立映射
右括号 → 同类型左括号。 - 扫描
s:遇到左括号就入栈;遇到右括号就检查「栈非空且栈顶等于映射值」,满足则出栈,否则返回false。 - 扫描结束后,栈为空返回
true,非空返回false。
以 "{[()]}" 为例(栈按“底部 → 顶部”表示):
| 读入 | 动作 | 栈(底 → 顶) |
|---|---|---|
{ | 左括号入栈 | { |
[ | 左括号入栈 | { [ |
( | 左括号入栈 | { [ ( |
) | 栈顶 ( 匹配,出栈 | { [ |
] | 栈顶 [ 匹配,出栈 | { |
} | 栈顶 { 匹配,出栈 | (空) |
扫描完且栈为空,因此合法。
下图把上面 3 个步骤串成流程,并逐步演示:


C++
class Solution {
public:本篇为付费内容
您已阅读试读部分,购买后即可解锁全文。
⚠️ 本站内容已做唯一性标记并受版权保护,未经授权禁止转载,侵权必究。
还没有评论,来说两句?