题目
!! 题目来源:有效括号 - 力扣
分析
要解决这个问题,我们可以借助一种数据结构:栈。
当然,大家肯定对栈相当熟悉,但这里还是简单啰嗦两句 —— 所谓栈,就是元素先进后出的数据结构,大致如下图所示:
了解了栈,那么这个问题也就迎刃而解了:
- 创建一个栈,遍历字符串
- 当遇到左括号,即
(, [, {的时候,将其入栈 - 当遇到右括号,即
), ], }的时候将栈顶元素出栈,并查看是否与当前元素匹配- 如果匹配则继续循环
- 否则直接返回
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;
};
结果如下:
优化
上面的代码虽然解决了问题,但有很多的无效逻辑,这里可以优化一些判断:
- 当 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;
};
结果如下:
!! 顺带一提,力扣那个官方解答思路是对的,但结果报错的原因是用了 forEach,return 不会结束循环