力扣hot100 20.有效的括号 解析

题目描述

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

**输入:**s = "()"

**输出:**true

示例 2:

**输入:**s = "()[]{}"

**输出:**true

示例 3:

**输入:**s = "(]"

**输出:**false

示例 4:

**输入:**s = "([])"

**输出:**true

示例 5:

**输入:**s = "([)]"

**输出:**false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

思路解析

一、题目到底在检查什么?

给你一个字符串,只包含:

( ) { } [ ]

问你一句话:

括号是否"合法配对 + 正确嵌套"

合法的例子

复制代码
() ()[]{} {[()]} 

不合法的例子

复制代码
(] ([)] ((( 

二、什么叫「合法」?

合法 ≠ 数量相等

合法 = 三条规则同时满足


规则 1:左括号必须被右括号关闭

复制代码

(

不合法(没关)


规则 2:右括号必须匹配同类型的左括号

复制代码

(]

类型不对


规则 3:括号必须 后开先关(嵌套顺序)

([)]

你开的是:

复制代码

( → [

你关的时候却是:

) → ]

顺序错了


三、为什么「栈」是唯一正确模型?


括号的本质是「最近的要先关」

例子:

复制代码

{ [ ( ) ] }

执行顺序:

  1. {

  2. [

  3. (

  4. ) → 只能关最近的 (

  5. ] → 只能关 [

  6. } → 只能关 {

这就是一句话:

后进先出(LIFO)

的特性就是:

复制代码

后进先出


如果不用栈,会发生什么?

比如用变量记录?

  • 你最多记一个

  • 一旦嵌套多层就崩了

所以 栈是唯一自然模型


四、整体算法思路

从左到右扫描字符串

  • 遇到左括号:压栈

  • 遇到右括号:

    • 看栈顶是不是对应的左括号

    • 是 → 弹出

    • 不是 → 立刻非法

      最后:栈必须为空


代码实现

java 复制代码
class Solution {

    /**
     * 判断一个只包含 () {} [] 的字符串是否是「有效括号」
     */
    public boolean isValid(String s) {

        // ① 如果字符串长度是奇数:
        //    括号一定无法成对出现,直接返回 false(提前剪枝)
        if (s.length() % 2 == 1) {
            return false;
        }

        // 字符串总长度
        int n = s.length();

        // ② 建立「右括号 -> 左括号」的映射关系
        //    作用:当遇到右括号时,能立刻知道它期望匹配的左括号是什么
        Map<Character, Character> mp = new HashMap<>();
        mp.put(')', '(');
        mp.put('}', '{');
        mp.put(']', '[');

        // ③ 使用栈(Deque)来存放尚未被匹配的左括号
        //    栈的特点是:后进先出,正好符合括号"后开的先关"的规则
        Deque<Character> stack = new LinkedList<>();

        // ④ 从左到右遍历字符串中的每一个字符
        for (int i = 0; i < n; i++) {

            // 取出当前字符
            char ch = s.charAt(i);

            // ⑤ 如果当前字符是右括号
            //    (因为 mp 中只存了右括号作为 key)
            if (mp.containsKey(ch)) {

                // ⑥ 出现右括号时,必须满足两个条件:
                //    1)栈不能是空的(否则说明没有对应的左括号)
                //    2)栈顶元素必须是这个右括号对应的左括号
                if (stack.isEmpty() || stack.peek() != mp.get(ch)) {
                    // 只要有一个条件不满足,说明括号不合法
                    return false;
                } else {
                    // ⑦ 如果匹配成功:
                    //    当前这一对括号合法,弹出栈顶左括号
                    stack.pop();
                }

            } else {
                // ⑧ 如果当前字符是左括号:
                //    无法立即判断是否合法,只能先压入栈中
                //    等后续遇到右括号时再进行匹配
                stack.push(ch);
            }
        }

        // ⑨ 遍历结束后:
        //    如果栈为空,说明所有左括号都被正确匹配
        //    如果栈不为空,说明存在多余的左括号,字符串不合法
        return stack.isEmpty();
    }
}
相关推荐
苦藤新鸡2 小时前
29.删除倒数第N个节点
数据结构·链表·力扣
brave_zhao2 小时前
如何解决 Spoon 与 Carte 互联的 UTF-8 编码问题
java
CrazyClaz2 小时前
负载均衡算法
算法·负载均衡
重生之我是Java开发战士2 小时前
【数据结构】Map、Set与哈希表底层原理
java·数据结构·散列表
嵌入式小能手2 小时前
飞凌嵌入式ElfBoard-系统信息与资源之休眠
c语言·开发语言·算法
L.EscaRC2 小时前
深度解析 Spring 框架核心代理组件 MethodProxy.java
java·开发语言·spring
拽着尾巴的鱼儿2 小时前
Spring 缓存 @Cacheable 实现原理
java·spring·缓存
dabidai2 小时前
JSR-250JavaEE规范
java
Jackson@ML2 小时前
2026最新版IntelliJ IDEA安装使用指南
java·ide·intellij-idea