前言刷算法题时,很多人会陷入「当时看懂、过段时间就忘」的困境。根本原因不是复习不够,而是理解跳步、只记代码步骤,没有打通每一行逻辑的底层关联。以有效括号为例,完整梳理无跳步、强关联的闭环思路,全程逻辑自洽,适合长期记忆,也适合沉淀复盘。
一、题目核心要求给定仅包含 ()[]{} 的字符串,判定是否为有效括号,需满足两大硬性规则:
- 闭合顺序合法:右括号必须和最近未闭合的左括号匹配;
- 整体数量合法:所有左括号,最终都必须完成闭合。
二、数据结构选型:为什么必须用栈题目核心要求「就近匹配、后开先闭」,完全贴合栈后进先出的固有特性:后出现的左括号需要优先闭合,栈顶永远保留最新、待匹配的括号标记,是该场景下的最优结构。
三、整体核心思路
- 遍历字符串,识别三类左括号,提前压入对应的右括号,作为待闭合标记;
- 遍历到右括号时,做双重校验:栈内有待闭合标记、当前括号与栈顶匹配;
- 不满足匹配条件,直接判定无效;匹配成功则消除栈顶标记;
- 字符串遍历完成后,校验栈结构:无剩余标记,代表全部正常闭合。
四、分步逻辑详解
- 初始化用列表模拟栈,专门存放等待闭合的右括号标记。
- 左括号处理遍历字符,若识别到 ( [ { 三类左括号:直接压入一一对应的右括号。提前绑定对应关系,简化后续匹配判断,减少冗余分支。
- 右括号合法匹配处理非左括号,即为右括号。合法匹配必须同时满足两个条件:
- 栈不为空:保证前方存在未闭合的左括号,杜绝右括号单独前置的错误情况;
- 当前字符与栈顶元素一致:保证括号类型一一对应。两项条件同时满足,代表正常闭合,执行出栈操作,消除待匹配标记。
- 非法情况统一拦截但凡不满足以上所有合法条件,统一判定括号无效,直接返回结果。
- 最终全局校验单次遍历只能校验顺序与即时匹配,无法规避「左括号过多、缺少闭合」的问题。遍历结束后,若栈内仍有残留元素,说明存在未闭合的左括号,整体无效;栈为空,代表所有括号全部完成规范闭合,判定有效。
五、完整代码实现 class Solution: def isValid(self, s: str) -> bool: stack = [] for i in s: if i =='(': stack.append(')') elif i =='[': stack.append(']') elif i =='{': stack.append('}') elif stack and i == stack[-1]: stack.pop() else: return False return not stack`
六、踩坑复盘|理解不深刻的核心问题
- 忽略栈空判断直接读取栈顶元素,右括号前置时会触发索引报错。栈空判断,是拦截非法前置右括号的关键。
- 缺少末尾栈校验只关注遍历过程的匹配,忽略左括号冗余场景,造成用例判定错误。
- 逻辑跳步记忆只背诵压栈、出栈流程,不理解「预存右括号」「双重条件校验」的设计目的,短期能做题,长期极易遗忘。
七、核心本质总结
- 栈的作用:存储所有待闭合的括号标记;
- 左括号逻辑:预存对应右括号,绑定匹配关系;
- 右括号逻辑:先验存量、再验类型,匹配则抵消,异常则直接驳回;
- 收尾逻辑:空栈代表完全闭合,残栈代表结构残缺。