题目重点:以三种括号训练版说明嵌套顺序为何要用栈,并处理多余右括号与非法字符。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练输入只允许 `()[]{}` 六种括号,空串有效;出现其它字符返回 false。
- 若实际原题只含一类圆括号,可用计数器 O(1) 空间;若允许普通文本则应跳过非括号字符,而非照搬训练版的拒绝规则。
解题路线
- 扫描字符串,左括号压栈;右括号要立即与栈顶左括号的类型匹配,不匹配或栈空即拒绝。
- 扫描结束要求栈空,否则仍有未闭合左括号。栈不变量:其中正好存尚未被匹配的左括号,顺序为从外到内。
- 长度为奇数可提前判无效,但含非法字符时仍需验证规则;核心实现为一遍扫描。
- 对 137,257 个长度 ≤6 的括号/非法字符短串,使用独立的相邻配对反复消去语法判定进行对照。
手动走一遍
`([])` 依次压 `(`、`[`,遇 `]` 先弹 `[`,遇 `)` 再弹 `(`,有效;`([)]` 遇 `)` 时栈顶是 `[`,立即拒绝。仅比较各类括号数量会错判后一例。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def valid_brackets(text: str) -> bool:
"""Training format: only (), [] and {} characters are allowed."""
opening = "([{"
closing_to_opening = {")": "(", "]": "[", "}": "{"}
stack: list[str] = []
for char in text:
if char in opening:
stack.append(char)
elif char in closing_to_opening:
if not stack or stack.pop() != closing_to_opening[char]:
return False
else:
return False
return not stack
复杂度
O(n) 时间,栈最坏 O(n) 空间;仅一种括号类型时用计数器可 O(1) 空间,但多种嵌套类型无法只靠各类数量判断。
易错点与追问
容易失分的边界
- 只看左右括号总数相等,漏掉顺序或类型错配。
- 右括号出现时栈空仍尝试 pop。
- 扫描结束忘记检查残留左括号。
- 把普通字符处理策略猜成原题规则。
- 用递归解析长串却忽视调用栈上限。
继续深挖
- 仅 `()` 时怎样用一个整数验证?
- 如果要指出第一个错误位置与期望括号,返回值怎样设计?
- 允许引号中的括号不参与匹配时怎样解析转义?
- 如何把匹配扩展到 HTML 类标签?
