【练习】力扣热题100 有效的括号

题目

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

有效字符串需满足:

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

输入:s = "()"

输出:true
示例 2:

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

输出:true
示例 3:

输入:s = "(]"

输出:false
示例 4:

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

输出:true

来源:力扣热题100 有效的括号


题解

c 复制代码
class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        stack<char> st;
        for(int i = 0; i < n; i ++)
        {
            if(s[i] == '(' || s[i] == '[' || s[i] == '{')
                st.push(s[i]);
            else
            {
                if(st.empty())
                    return false;
                if(st.top() == '(' && s[i] != ')')
                    return false; 
                if(st.top() == '[' && s[i] != ']')
                    return false; 
                if(st.top() == '{' && s[i] != '}')
                    return false; 
                st.pop();
                if(st.empty() && i == n - 1)
                    return true;
            }
        }
        return false;
    }
};

题解(优化)

c 复制代码
class Solution {
public:
    bool isValid(string s) {
        int n = s.size();
        if (n % 2 == 1) {
            return false;
        }

        unordered_map<char, char> pairs = {
            {')', '('},
            {']', '['},
            {'}', '{'}
        };
        stack<char> stk;
        for (char ch: s) {
            if (pairs.count(ch)) {
                if (stk.empty() || stk.top() != pairs[ch]) {
                    return false;
                }
                stk.pop();
            }
            else {
                stk.push(ch);
            }
        }
        return stk.empty();
    }
};

以下是代码的详细分析:


pairs.count(ch) 的作用

  • pairs.count(ch) 是 C++ 中 unordered_map 的成员函数,用于检查键 ch 是否存在于哈希表 pairs 中。
  • 返回值:
    • 如果 ch 是 pairs 的键(即 ch 是右括号 )、] 或 }),则返回 1。
    • 如果 ch 不是 pairs 的键(即 ch 是左括号或其他字符),则返回 0。

代码逻辑分析:

  1. 检查字符串长度:

    cpp 复制代码
    int n = s.size();
    if (n % 2 == 1) {
        return false;
    }
    • 如果字符串的长度是奇数,则括号一定无法完全匹配,直接返回 false。
  2. 定义括号映射:

    cpp 复制代码
    unordered_map<char, char> pairs = {
        {')', '('},
        {']', '['},
        {'}', '{'}
    };
    • 使用一个哈希表 pairs 来存储右括号和对应的左括号的映射关系。
    • 例如,')' 对应 '(',']' 对应 '[','}' 对应 '{'。
  3. 使用栈进行匹配:

    cpp 复制代码
    stack<char> stk;
    for (char ch: s) {
        if (pairs.count(ch)) {
            if (stk.empty() || stk.top() != pairs[ch]) {
                return false;
            }
            stk.pop();
        }
        else {
            stk.push(ch);
        }
    }
    • 遍历字符串中的每个字符:
      • 如果当前字符是右括号(即 pairs.count(ch) 为真):
        • 检查栈是否为空,或者栈顶元素是否与当前右括号对应的左括号匹配。
        • 如果不匹配,则返回 false。
        • 如果匹配,则将栈顶元素弹出。
      • 如果当前字符是左括号,则将其压入栈中。
  4. 检查栈是否为空:

    cpp 复制代码
    return stk.empty();
    • 如果栈为空,说明所有括号都匹配成功,返回 true。
    • 如果栈不为空,说明有未匹配的左括号,返回 false。

举例说明:

假设输入字符串为 s = "()[]{}",运行过程如下:

  1. 初始化:

    • stk = [](空栈)。
  2. 遍历字符:

    • ch = '(':是左括号,压入栈中。stk = ['(']。
    • ch = ')':是右括号,检查栈顶元素 '(' 是否匹配。匹配,弹出栈顶元素。stk = []。
    • ch = '[':是左括号,压入栈中。stk = ['[']。
    • ch = ']':是右括号,检查栈顶元素 '[' 是否匹配。匹配,弹出栈顶元素。stk = []。
    • ch = '{':是左括号,压入栈中。stk = ['{']。
    • ch = '}':是右括号,检查栈顶元素 '{' 是否匹配。匹配,弹出栈顶元素。stk = []。
  3. 最终检查:

    • 栈为空,返回 true。

时间复杂度:

  • O(n) ,其中 n 是字符串的长度。每个字符只会被压入栈和弹出栈一次。

空间复杂度:

  • O(n) ,在最坏情况下(例如全是左括号),栈的大小为 n/2。

代码的改进建议:

  1. 使用数组代替哈希表:

    • 由于括号字符的 ASCII 值是连续的,可以使用数组代替哈希表来存储映射关系,进一步提高性能。

    改进后的代码:

    cpp 复制代码
    class Solution {
    public:
        bool isValid(string s) {
            int n = s.size();
            if (n % 2 == 1) {
                return false;
            }
    
            char pairs[256] = {0}; // 初始化所有字符映射为 0
            pairs[')'] = '(';
            pairs[']'] = '[';
            pairs['}'] = '{';
    
            stack<char> stk;
            for (char ch: s) {
                if (pairs[ch]) {
                    if (stk.empty() || stk.top() != pairs[ch]) {
                        return false;
                    }
                    stk.pop();
                }
                else {
                    stk.push(ch);
                }
            }
            return stk.empty();
        }
    };

总结:

这段代码通过栈和哈希表的方法,高效地解决了括号匹配问题。它的时间复杂度为 O(n) ,空间复杂度为 O(n),并且能够处理各种边界情况。如果需要进一步优化,可以使用数组代替哈希表,或者添加更多的边界条件处理。

相关推荐
充值内卷6 分钟前
[特殊字符] 自己动手做一个类 tldraw 的桌面白板:StepDraw 开源啦(C++ + WebView2 + Canvas)
开发语言·c++
raindayinrain8 分钟前
c++对象模型--内存布局,多态,运行时类型识别
开发语言·c++
怕浪猫20 分钟前
不用摄像机,我把历史故事做成竖屏视频
算法·面试·github
郝学胜-神的一滴1 小时前
AI 编程智能体 16:从零基础搭建到精细化优化
人工智能·python·算法·语言模型·langchain·pip
cu1431 小时前
细谈IT6653的具体功能与其应用
c语言·c++·单片机·嵌入式硬件
喜欢打篮球的普通人1 小时前
AI 编译器内存分配算法:从静态/动态划分到内存复用
人工智能·算法
夏虫不可与之言冰2 小时前
RMT 与 WS2812 灯带:可寻址 RGB 全彩控制
c语言·c++·单片机·物联网·visual studio
起个名字都难啊2 小时前
visual studio C/C++空项目修改为CUDA c++
c++·windows·visual studio
mjhcsp2 小时前
Code date creation v8.0 竞赛数据生成与对拍实战指南
算法·ai·深度优先·cdc
羊锦磊2 小时前
嵌入式基础1
c语言·c++·gnu