当前位置: 首页 > news >正文

【LeetCode 热题 100】20. 有效的括号

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

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N)
    • 空间复杂度:O(N)

整体思路

这段代码旨在解决一个非常经典的计算机科学问题:有效的括号 (Valid Parentheses)。问题要求判断一个只包含 ( ) { } [ ] 六种括号的字符串是否是“有效”的。有效性有两个标准:1. 左括号必须用相同类型的右括号闭合。2. 左括号必须以正确的顺序闭合。

该算法采用的是解决此类问题的标准且最高效的方法:栈 (Stack)。其核心逻辑思想是,利用栈“后进先出”(LIFO)的特性来完美匹配括号的嵌套结构。

  1. 预处理与数据结构选择

    • 快速失败:代码首先进行了一个简单的优化判断 s.length() % 2 != 0。一个有效的括号字符串,其长度必然是偶数。如果长度为奇数,可以直接判定为无效,提前返回 false
    • 栈的选择:算法的核心是一个栈(在Java中通过 Deque 接口和 ArrayDeque 实现类来创建)。这个栈用来存储所有遇到的、但尚未匹配到相应右括号的左括号
    • 匹配关系:为了方便地查找一个右括号对应的左括号,代码使用了一个 HashMapMap的键是右括号,值是对应的左括号。这使得匹配查询操作的效率为 O(1)。
  2. 单次遍历与匹配逻辑

    • 算法通过一次 for 循环遍历输入字符串 s 中的每一个字符 c
    • 遇到左括号:如果当前字符 c 是一个左括号(通过 !mp.containsKey(c) 判断,因为只有右括号是 Map 的键),就将其压入栈中,等待后续的右括号来匹配。
    • 遇到右括号:如果当前字符 c 是一个右括号,则进入匹配逻辑:
      a. 栈空检查:首先检查栈是否为空。如果为空,说明遇到了一个右括号,但之前没有任何未匹配的左括号,这显然是无效的(例如 ")""{})")。
      b. 类型匹配:如果栈不为空,就从栈顶弹出一个元素(st.pop())。这个弹出的元素应该是最近遇到的、未闭合的左括号。然后,将这个弹出的左括号与当前右括号 c 对应的正确左括号(mp.get(c))进行比较。如果它们不相等,说明括号类型不匹配(例如 "(]"),字符串无效。
  3. 最终校验

    • 当遍历完整个字符串后,如果字符串是完全有效的,那么所有的左括号都应该找到了对应的右括号并被从栈中弹出。因此,最后需要检查栈是否为空 (st.isEmpty())。
    • 如果栈为空,说明所有括号都完美匹配,字符串有效。
    • 如果栈不为空,说明有剩余的左括号没有被闭合(例如 "(""{[()"),字符串无效。

完整代码

class Solution {/*** 判断一个只包含 '(', ')', '{', '}', '[' 和 ']' 的字符串是否有效。* @param s 输入的括号字符串* @return 如果字符串有效则返回 true,否则返回 false*/public boolean isValid(String s) {// 快速失败优化:有效的括号字符串长度必为偶数。if (s.length() % 2 != 0) {return false;}// 创建一个 Map 存储括号的匹配关系(key:右括号, value:左括号)。// 使用实例初始化块(双大括号语法)来方便地初始化 Map。Map<Character, Character> mp = new HashMap<>() {{put(')', '(');put('}', '{');put(']', '[');}};// 使用 Deque 作为栈,这是 Java 中推荐的栈实现方式。// st 用于存储所有遇到的、但尚未匹配的左括号。Deque<Character> st = new ArrayDeque<>();// 遍历字符串中的每一个字符for (char c : s.toCharArray()) {// 如果当前字符 c 是一个左括号(即它不是 Map 的键)if (!mp.containsKey(c)) {// 将左括号压入栈中st.push(c);} // 如果当前字符 c 是一个右括号else if (st.isEmpty() || st.pop() != mp.get(c)) {// 检查两种无效情况:// 1. st.isEmpty(): 栈中没有左括号来匹配当前的右括号 (例如 "())")// 2. st.pop() != mp.get(c): 栈顶的左括号与当前右括号类型不匹配 (例如 "(]")// 如果任一情况为真,则字符串无效。return false;}}// 遍历完所有字符后,如果栈为空,说明所有括号都完美匹配。// 如果栈不为空,说明有未闭合的左括号。return st.isEmpty();}
}

时空复杂度

时间复杂度:O(N)

  1. 字符串遍历:算法的核心是一个 for 循环,它遍历输入字符串 s 的所有字符一次。如果字符串的长度为 N,那么循环将执行 N 次。
  2. 循环内部操作
    • mp.containsKey(): HashMap 的查找操作,平均时间复杂度为 O(1)
    • st.push(): ArrayDeque 作为栈的压入操作,均摊时间复杂度为 O(1)
    • st.isEmpty(): 检查是否为空,时间复杂度为 O(1)
    • st.pop(): ArrayDeque 作为栈的弹出操作,均摊时间复杂度为 O(1)
    • mp.get(): HashMap 的获取操作,平均时间复杂度为 O(1)
  3. 综合分析
    • 整个算法由 N 次 O(1) 的操作组成。因此,总的时间复杂度是线性的,即 O(N)

空间复杂度:O(N)

  1. 主要存储开销:算法的额外空间主要由 MapDeque (栈) 占用。
    • Map<Character, Character> mp: 这个 Map 存储了固定数量的键值对(3对)。其大小与输入字符串的长度 N 无关,因此它占用的空间是常数级别的,即 O(1)
    • Deque<Character> st: 这个栈用于存储未匹配的左括号。在最坏的情况下,输入字符串可能全是左括号,例如 "((((..."。在这种情况下,栈的大小会增长到与输入字符串长度 N 相同。

综合分析
算法所需的额外空间主要由栈 st 的大小决定。因此,在最坏情况下,空间复杂度为 O(N)

参考灵神

http://www.dtcms.com/a/308318.html

相关文章:

  • 使用 Docker 部署 Apache RocketMQ
  • 数据转换能干什么?有哪些好用的数据转换方法?
  • 剖析客户服务痛点,借助 Baklib 整合多渠道反馈
  • ADW300 物联网仪表:引领能源计量智能化变革
  • STM32标准库搭建示例(STM32F103C8T6)
  • 操作系统:上下文切换(Context Switch)
  • Effective C++ 条款13:以对象管理资源
  • LLC电源原边MOS管DS增加RC吸收对ZVS的影响分析
  • Linux和shell
  • 保姆级别IDEA关联数据库方式、在IDEA中进行数据库的可视化操作(包含图解过程)
  • ceph sc 设置文件系统格式化参数
  • 前端ESLint扩展的用法详解
  • 【实时Linux实战系列】实时图像处理应用开发
  • 【PHP类的基础概念:从零开始学面向对象】
  • Elasticsearch DSL 核心语法大全:match、bool、range、聚合查询实战解析
  • 使用神经网络与5折交叉验证进行基因组预测:基础知识指南
  • Java【代码 21】将word、excel文件转换为pdf格式和将pdf文档转换为image格式工具类分享(Gitee源码)aspose转换中文乱码问题处理
  • 智谱 AI 重磅发布 GLM-4.5:开源 SOTA,专为下一代智能体应用打造
  • 微服务架构技巧篇——接口类设计技巧
  • review|
  • Day15--二叉树--222. 完全二叉树的节点个数,110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和
  • 企业级部署 (基于tomcat与nginx)
  • 新书速览|R语言数据分析从入门到实践
  • Linux大页内存导致服务内存不足
  • Docker部署的PostgreSQL慢查询日志配置指南
  • 当文档包含图文混排表格时,如何结合大模型(如DeepSeek-VL)和OCR提取数据
  • 468. 验证IP地址
  • Ps2025
  • Python字典完全指南:从基础到实战(2025版)
  • 03 基于sklearn的机械学习-线性回归、损失函数及其推导