题目重点:用栈维护尚未闭合的开括号,遇闭括号必须匹配栈顶;区分数量相等与真正嵌套合法。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练输入只包含 ()[]{},空串视为合法;若混有普通字符,代码报错而非默认忽略。
- 合法要求每个闭括号对应最近未闭合的同类开括号,且最终无剩余开括号。
- 只返回 bool,不返回错误位置。
解题路线
- 扫描左到右,开括号入栈;闭括号必须与栈顶的对应开括号相同,否则立即失败。
- 扫描结束仅当栈空才成功。栈不变量是当前前缀所有尚未闭合的开括号,按嵌套由外到内排列。
- 正确性:任一合法匹配的闭括号必须先结束最内层尚未关闭的括号,恰是栈顶;失败时后续字符无法修复此前错误嵌套。
手动走一遍
'([])' 的栈依次入 '('、'[',再弹 '['、'(',合法;'([)]' 虽各类数量相同,但读到 ')' 时栈顶是 '[',立即失败;'(()' 结束仍有 '(',失败。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
"""Check whether (), [], and {} brackets are properly nested."""
def valid_brackets(text: str) -> bool:
matching = {")": "(", "]": "[", "}": "{"}
openings = set(matching.values())
stack = []
for character in text:
if character in openings:
stack.append(character)
elif character in matching:
if not stack or stack.pop() != matching[character]:
return False
else:
raise ValueError("bracket-only input required")
return not stack
复杂度
n 个字符各入/出栈最多一次,O(n) 时间;最坏全是开括号时 O(n) 空间。
易错点与追问
容易失分的边界
- 只比较左右括号数量,不看嵌套顺序。
- 闭括号时栈空仍尝试 pop。
- 遍历结束不检查剩余开括号。
- 输入允许普通字符与否未澄清,却把它们默默跳过。
继续深挖
- 如何返回第一个错误下标与期望括号?
- 输入流分块时如何跨块保存栈状态?
- 若只有一种括号,为什么仍要追踪前缀余额非负?
