LeetCode 第20题:有效的括号

LeetCode 第20题:有效的括号

题目描述

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

有效字符串需满足:

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

难度

简单

题目链接

https://leetcode.cn/problems/valid-parentheses/

示例

示例 1:

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

示例 2:

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

示例 3:

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

示例 4:

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

提示

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

解题思路

方法:栈

这是一道经典的栈应用题目。我们可以使用栈来解决这个问题,具体思路如下:

关键点:

  1. 遇到左括号就入栈
  2. 遇到右括号就与栈顶元素匹配
  3. 最后栈应该为空

具体步骤:

  1. 创建一个栈来存储左括号
  2. 遍历字符串:
    • 如果是左括号,入栈
    • 如果是右括号:
      • 如果栈为空,返回false
      • 如果与栈顶括号不匹配,返回false
      • 如果匹配,弹出栈顶元素
  3. 最后检查栈是否为空

时间复杂度:O(n),其中n是字符串长度
空间复杂度:O(n),最坏情况下需要存储所有字符

代码实现

C# 实现

public class Solution {
    public bool IsValid(string s) {
        // 如果字符串长度为奇数,一定不是有效的括号
        if (s.Length % 2 == 1) {
            return false;
        }
      
        // 创建栈来存储左括号
        Stack<char> stack = new Stack<char>();
      
        // 遍历字符串
        foreach (char c in s) {
            // 如果是左括号,入栈
            if (c == '(' || c == '[' || c == '{') {
                stack.Push(c);
            }
            // 如果是右括号
            else {
                // 如果栈为空,说明没有匹配的左括号
                if (stack.Count == 0) {
                    return false;
                }
              
                // 获取栈顶元素
                char top = stack.Pop();
              
                // 检查是否匹配
                if (c == ')' && top != '(' ||
                    c == ']' && top != '[' ||
                    c == '}' && top != '{') {
                    return false;
                }
            }
        }
      
        // 最后检查栈是否为空
        return stack.Count == 0;
    }
}

优化版本(使用字典)

public class Solution {
    public bool IsValid(string s) {
        if (s.Length % 2 == 1) {
            return false;
        }
      
        // 使用字典存储括号对应关系
        Dictionary<char, char> pairs = new Dictionary<char, char> {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
      
        Stack<char> stack = new Stack<char>();
      
        foreach (char c in s) {
            // 如果是右括号
            if (pairs.ContainsKey(c)) {
                if (stack.Count == 0 || stack.Pop() != pairs[c]) {
                    return false;
                }
            }
            // 如果是左括号
            else {
                stack.Push(c);
            }
        }
      
        return stack.Count == 0;
    }
}

代码详解

基本版本:

  1. 长度检查:
    • 如果字符串长度为奇数,一定不是有效的括号
  2. 栈的使用:
    • 使用Stack存储左括号
    • 遇到右括号时检查匹配关系
  3. 匹配检查:
    • 检查右括号是否与栈顶左括号匹配
    • 不匹配则返回false

优化版本:

  1. 使用字典:
    • 存储右括号到左括号的映射关系
    • 简化匹配逻辑
  2. 代码更简洁:
    • 减少了if-else判断
    • 逻辑更清晰

执行结果

基本版本:

  • 执行用时:72 ms
  • 内存消耗:37.1 MB

优化版本:

  • 执行用时:68 ms
  • 内存消耗:37.3 MB

总结与反思

  1. 这是一道经典的栈应用题目:
    • 体现了栈的LIFO特性
    • 处理嵌套结构的典型案例
  2. 优化思路:
    • 使用字典简化代码
    • 提前判断无效情况
  3. 注意事项:
    • 处理栈为空的情况
    • 最后检查栈是否清空
    • 考虑字符串长度为奇数的情况

相关题目

posted @ 2025-02-13 21:47  旧厂街小江  阅读(10)  评论(0)    收藏  举报