20. 有效的括号

Origin: LeetCode 20

题目描述

给定一个只包含 (, ), {, }, [, ] 的字符串 s,判断字符串是否有效。有效字符串需满足:左括号必须用相同类型的右括号闭合,左括号必须以正确的顺序闭合。

示例

Input: s = "()" Output: true

Input: s = "()[]{}" Output: true

Input: s = "(]" Output: false

Input: s = "([)]" Output: false

Input: s = "{[]}" Output: true

约束

  • 1 <= s.length <= 10
  • s 仅由括号字符组成

关键信息

  • 你做过 HackerRank 第 8 题(括号匹配),栈的经典应用
  • 左括号 push,右括号 pop 检查是否匹配
  • 最后栈空则有效

Resolution

我的解法

function isValid(s: string): boolean {
    const lefts = ['{', '[', '(']
    const rights = ['}', ']', ')']
    const map: { [k: string]: string } = {
        '}': '{',
        ']': '[',
        ')': '('
    }
    const stack = []
    for (let i = 0; i < s.length; i++) {
        let cur = s[i]
        if (lefts.includes(cur)) {
            stack.push(cur)
        } else if (rights.includes(cur)) {
            const poped = stack[stack.length - 1]
            if (map[cur] === poped) {
                stack.pop()
            } else {
                return false
            }
        }
    }
    return !stack.length
}

标准解法(单 map)

function isValid(s: string): boolean {
    const map: { [k: string]: string } = {
        '}': '{',
        ']': '[',
        ')': '('
    }
    const stack = []
    for (const c of s) {
        if (c in map) {
            if (stack.pop() !== map[c]) return false
        } else {
            stack.push(c)
        }
    }
    return !stack.length
}

c in map 判断左右括号,不需要 lefts/rights 两个数组。stack.pop() !== map[c] 一行搞定判断+弹出。我的解法的好处是 lefts/rights 可以排除掉非括号字符,更健壮。

栈的经典应用。左括号 push,右括号查栈顶是否匹配:

  • 匹配 → pop
  • 不匹配 → false
  • 遍历完栈空 → true

踩坑

  • 最后要检查栈是否为空,return !stack.length,因为可能有未闭合的左括号
  • ([)] 是 false:栈顶是 [ 但来了 ),不匹配

复杂度

  • 时间:O(n)
  • 空间:O(n)