栈与队列相关的问题就比较微妙了,很多时候相关题目中压根不会出现“栈”、“队列”这样的关键字,但只要你深入到真题里去、对栈和队列的应用场景建立起正确的感知,那么很多线索都会在分析的过程中被你轻松地挖掘出来。

这里也和大家分享一位读者在试读过程中的学习感悟:

感觉算法题除了理解还要靠练习,就像高考数学题,要锻炼出解题常规思维。任重道远啊🙊

其实就是这么回事,这也正是我们开篇就跟大家指明“以题为纲”这条路的初衷。

好啦,开工了老哥们!

# 典型真题快速上手-“有效括号”问题

⚡ 30 秒速记

  • 括号嵌套 = 最后打开的最先关闭 = 栈的后进先出
  • 遇到左括号,把「期待的右括号」压栈;遇到右括号,和栈顶比
  • 栈空时来了右括号、或者和栈顶对不上 → 立刻 false
  • 扫完还要 stack.length === 0,不然 (( 会被判对
  • 时间 O(n),最坏空间 O(n);奇数长度可以直接 false

看到括号匹配就想到栈:最后打开的括号必须最先关上,这正是后进先出。 我的写法是遇到左括号就把对应的右括号压进去,遇到右括号就弹出栈顶比一下,对不上或者栈已经空了就直接返回 false。扫完一遍还要检查栈是不是空的,剩下的就是没关上的左括号。

const pair = { '(': ')', '[': ']', '{': '}' }
function isValid(s) {
  const stack = []
  for (const ch of s) {
    if (pair[ch]) stack.push(pair[ch])
    else if (stack.pop() !== ch) return false
  }
  return stack.length === 0
}
isValid('([)]') // false
isValid('{[]}') // true

回答参考:“括号嵌套要求最后打开的括号最先关闭,正好符合 LIFO。我把期望的闭括号压栈,右括号只需和栈顶比较。”

题目描述:给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

示例 1:

  • 输入: "()"
  • 输出: true

示例 2:

  • 输入: "()[]{}"
  • 输出: true

示例 3:

  • 输入: "(]"
  • 输出: false

示例 4:

  • 输入: "([)]"
  • 输出: false

示例 5:

  • 输入: "{[]}"
  • 输出: true

思路分析

括号问题在面试中出现频率非常高, 这类题目我们一般首选用栈来做。

为什么可以用栈做?大家想想,括号成立意味着什么?意味着对称性。

巧了,根据栈的后进先出原则,一组数据的入栈和出栈顺序刚好是对称的。比如说1、2、3、4、5、6按顺序入栈,其对应的出栈序列就是 6、5、4、3、2、1:

123456
654321
webapp
公众号
开发者导航
切换夜间模式
点击侧边栏上一篇
点击侧边栏下一篇
折叠侧边栏
收起全部