简单LeetCode 20可逐步演示引导学习
有效的括号
栈:最近打开的必须先闭合
用栈记录所有还没闭合的左括号:遇到左括号入栈,遇到右括号就和栈顶检查配对——后进先出,正好对应括号"最近打开的先闭合"的嵌套规则。
时间复杂度 O(n)空间复杂度 O(n)
题单:面试热题
题目描述
给定一个只包含字符 ()[]{} 的字符串 s,判断它是否合法:每个左括号都必须由同类型的右括号按正确顺序闭合(例如 "([])" 合法,"([)]" 不合法)。
学习目标
能说清括号匹配为什么是后进先出,并用栈写出正确的入栈、配对、弹出和最终判空。
已完成 0 / 6 阶段
诊断
先判断:数数量够不够
只统计左右括号数量相等,能判断括号合法吗?举一个反例。
下面哪个字符串左右括号数量相等但不合法?
建议先完成当前阶段(提示 / 检查 / 自评),再进入下一步;也可以直接跳过。
解题思路
核心思想
用栈记录所有还没闭合的左括号:遇到左括号入栈,遇到右括号就和栈顶检查配对——后进先出,正好对应括号"最近打开的先闭合"的嵌套规则。
为什么需要它
括号合法性的本质是嵌套结构(像洋葱):最内层的一对先闭合。这种"最近相关"的问题用别的结构都别扭——队列是先进先出,配不上"后打开的必须更早闭合";只数数量也不够,因为顺序会错。
第一反应:直觉方案
数一下左右括号数量是否相等?遇到反例:")(" 左右各一个、数量相等,但顺序是错的。数量相等只是必要条件,不是充分条件。
关键洞察
关键洞察是"嵌套 = 后进先出":把还没闭合的左括号按打开顺序存好,每遇到一个右括号,它必须和最新打开的那个配对——这恰好就是栈顶。于是"顺序对不对"不需要额外检查,栈的 LIFO 结构天然保证:如果最新打开的都没配上,更早打开的肯定也等不到正确的闭合。
时间复杂度 O(n)空间复杂度 O(n)
易错点
- 访问栈顶前必须先判断栈非空——否则第一个字符就是右括号时会出错
- 最后必须检查栈为空:"([]" 这类多余的左括号也要返回 false,只"遍历完"不算数
- 右括号不进栈:它只负责和栈顶检查、配对后弹出
逐步演示
参考代码
1function isValid(s) {
2 const stack = [];
3 const pairs = { ')': '(', ']': '[', '}': '{' };
4 for (const ch of s) {
5 if (Object.values(pairs).includes(ch)) {
6 stack.push(ch);
7 } else {
8 if (stack.length === 0 || stack[stack.length - 1] !== pairs[ch]) {
9 return false;
10 }
11 stack.pop();
12 }
13 }
14 return stack.length === 0;
15}
效果图
预测:答对 0 / 共 1 题
第 1 / 12 步