【Daily Interview】- 09 有效括号

253 阅读2分钟

题目

图片1
图片1

!! 题目来源:有效括号 - 力扣

分析

要解决这个问题,我们可以借助一种数据结构:栈。

当然,大家肯定对栈相当熟悉,但这里还是简单啰嗦两句 —— 所谓栈,就是元素先进后出的数据结构,大致如下图所示:

图片2
图片2

了解了栈,那么这个问题也就迎刃而解了:

  • 创建一个栈,遍历字符串
  • 当遇到左括号,即 (, [, { 的时候,将其入栈
  • 当遇到右括号,即 ), ], } 的时候将栈顶元素出栈,并查看是否与当前元素匹配
    • 如果匹配则继续循环
    • 否则直接返回 false

这里按照思路直接实现代码即可:

var isValid = function (s) {
  const stack = [];
  const left = ["(""[""{"];
  const right = [")""]""}"];
  const match = new Map([
    [")""("],
    ["]""["],
    ["}""{"]
  ]);
  for (let i = 0; i < s.length; i++) {
    const c = s[i];
    if (left.includes(c)) {
      stack.push(c);
    }
    if (right.includes(c)) {
      const _c = stack.pop();
      console.log("_c", _c);
      console.log("match.get(c)", match.get(c));
      if (_c !== match.get(c)) return false;
    }
  }

  return stack.length === 0;
};

结果如下:

图片3
图片3

优化

上面的代码虽然解决了问题,但有很多的无效逻辑,这里可以优化一些判断:

  • 当 s 的长度不为 2 的倍数的时候,显然括号是不可能匹配的,直接返回 false 即可
  • 可以先看看被遍历到的字符是不是右括号,这个时候如果 stack 为空或者将要 pop 的元素与之不匹配,也可以直接返回 false

那么我们可以这样优化一下代码:

var isValid = function (s) {
  if (s.length % 2 !== 0) return false;

  const stack = [];
  const match = new Map([
    [")""("],
    ["]""["],
    ["}""{"]
  ]);

  for (let i = 0; i < s.length; i++) {
    const c = s[i];
    if (match.has(c)) {
      if (!stack.length || stack[stack.length - 1] !== match.get(c)) {
        return false;
      }
      stack.pop();
    } else {
      stack.push(c);
    }
  }

  return !stack.length;
};

结果如下:

图片4
图片4

!! 顺带一提,力扣那个官方解答思路是对的,但结果报错的原因是用了 forEach,return 不会结束循环