(LeetCode-Hot100)20. 有效的括号

有效的括号

问题简介

LeetCode 20. 有效的括号

题目描述

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

有效字符串需满足:

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

示例说明

示例 1:

  • 输入:s = "()"
  • 输出:true

示例 2:

  • 输入:s = "()[]{}"
  • 输出:true

示例 3:

  • 输入:s = "(]"
  • 输出:false

示例 4:

  • 输入:s = "([)]"
  • 输出:false

示例 5:

  • 输入:s = "{[]}"
  • 输出:true

解题思路

方法一:栈(推荐解法)

💡 核心思想:利用栈的后进先出(LIFO)特性来匹配括号。

步骤详解:

  1. 初始化栈:创建一个空栈用于存储左括号
  2. 遍历字符串:逐个检查每个字符
  3. 遇到左括号:将左括号压入栈中
  4. 遇到右括号
    • 如果栈为空,说明没有对应的左括号,返回 false
    • 如果栈顶元素与当前右括号不匹配,返回 false
    • 如果匹配,弹出栈顶元素
  5. 最终检查:遍历完成后,如果栈为空,说明所有括号都正确匹配,返回 true;否则返回 false

方法二:替换法(不推荐,仅作了解)

💡 核心思想:不断替换相邻的有效括号对,直到无法替换为止。

步骤:

  1. 循环查找并替换 "()""[]""{}" 为空字符串
  2. 如果最终字符串为空,则有效;否则无效

缺点:时间复杂度较高,为 O(n²)

方法三:计数法(仅适用于单一类型括号)

💡 注意 :此方法不适用于本题,因为本题包含三种不同类型的括号,且需要考虑顺序。计数法只能处理单一类型括号的情况。

代码实现

tabs 复制代码
```java
import java.util.*;

public class Solution {
    public boolean isValid(String s) {
        // 使用栈来存储左括号
        Deque<Character> stack = new ArrayDeque<>();
        
        // 建立括号映射关系
        Map<Character, Character> pairs = new HashMap<>();
        pairs.put(')', '(');
        pairs.put(']', '[');
        pairs.put('}', '{');
        
        for (char c : s.toCharArray()) {
            if (pairs.containsKey(c)) {
                // 当前字符是右括号
                if (stack.isEmpty() || stack.peek() != pairs.get(c)) {
                    return false;
                }
                stack.pop();
            } else {
                // 当前字符是左括号
                stack.push(c);
            }
        }
        
        // 栈为空说明所有括号都匹配
        return stack.isEmpty();
    }
}
go 复制代码
func isValid(s string) bool {
    // 使用切片模拟栈
    stack := []rune{}
    
    // 建立括号映射关系
    pairs := map[rune]rune{
        ')': '(',
        ']': '[',
        '}': '{',
    }
    
    for _, char := range s {
        if left, exists := pairs[char]; exists {
            // 当前字符是右括号
            if len(stack) == 0 || stack[len(stack)-1] != left {
                return false
            }
            // 弹出栈顶元素
            stack = stack[:len(stack)-1]
        } else {
            // 当前字符是左括号
            stack = append(stack, char)
        }
    }
    
    // 栈为空说明所有括号都匹配
    return len(stack) == 0
}

示例演示

让我们通过示例 "([{}])" 来演示算法执行过程:

步骤 当前字符 栈状态 操作
1 ( [(] 压入左括号
2 [ [(, [] 压入左括号
3 { [(, [, {] 压入左括号
4 } [(, [] 匹配成功,弹出 {
5 ] [(] 匹配成功,弹出 [
6 ) [] 匹配成功,弹出 (
结束 - [] 栈为空,返回 true

答案有效性证明

正确性证明:

  1. 充分性:如果字符串有效,算法必然返回 true

    • 有效字符串中的每个右括号都能找到对应的左括号
    • 栈的操作保证了正确的匹配顺序
    • 最终栈必为空
  2. 必要性:如果算法返回 true,字符串必然有效

    • 算法确保每个右括号都与正确的左括号匹配
    • 栈为空说明没有多余的左括号
    • 所有括号都按正确顺序匹配
  3. 边界情况处理

    • 空字符串:返回 true(符合题目要求)
    • 只有左括号:栈不为空,返回 false
    • 只有右括号:栈为空时遇到右括号,返回 false

复杂度分析

复杂度类型 时间复杂度 空间复杂度
栈解法 O(n) O(n)
替换法 O(n²) O(1)

📌 详细分析:

  • 时间复杂度 O(n):只需要遍历字符串一次,每个字符最多进行一次入栈和出栈操作
  • 空间复杂度 O(n):最坏情况下(全是左括号),栈需要存储 n 个字符

问题总结

关键要点:

  1. 栈是解决括号匹配问题的标准数据结构
  2. 必须考虑三种不同类型的括号及其匹配关系
  3. 边界情况处理很重要(空字符串、只有左/右括号等)
  4. 映射表的使用让代码更清晰易懂

💡 扩展思考:

  • 如果增加更多类型的括号,只需在映射表中添加对应关系
  • 此解法可以轻松扩展到处理 HTML 标签匹配等问题
  • 在实际工程中,这种括号匹配常用于语法解析、表达式验证等场景

常见错误:

  • 忘记检查栈是否为空就直接访问栈顶元素
  • 没有正确建立括号的映射关系
  • 忽略了最终栈必须为空的条件

github地址: https://github.com/swf2020/LeetCode-Hot100-Solutions

相关推荐
瓦特what?2 小时前
快 速 排 序
数据结构·算法·排序算法
前路不黑暗@2 小时前
Java项目:Java脚手架项目的文件服务(八)
java·开发语言·spring boot·学习·spring cloud·docker·maven
niuniudengdeng2 小时前
基于时序上下文编码的端到端无文本依赖语音分词模型
人工智能·数学·算法·概率论
hetao17338372 小时前
2026-02-13~16 hetao1733837 的刷题记录
c++·算法
毅炼2 小时前
Java 集合常见问题总结(3)
java·开发语言·后端
百锦再3 小时前
Java多线程编程全面解析:从原理到实战
java·开发语言·python·spring·kafka·tomcat·maven
Cosmoshhhyyy3 小时前
《Effective Java》解读第38条:用接口模拟可扩展的枚举
java·开发语言
wangbing11253 小时前
平台介绍-主数据系统-同步消息设计
java
小冷coding4 小时前
【Java】最新Java高并发高可用平台技术选型指南(思路+全栈路线)
java·开发语言