leetcode 括号匹配相关题目

本文深入探讨了括号相关的算法问题,包括括号的有效性验证、括号生成、寻找最长有效括号子串及删除无效括号等。通过具体示例和代码实现,详细解析了每种问题的解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

leetcode 20. 有效的括号

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

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。

示例 1:

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

示例 2:

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

示例 3:

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

分析:此题借助栈,逐一分析即可。

class Solution {
public:
    bool isValid(string s) {
        stack<char> mystack;
        unordered_map<char, char> pairs = {
            {'}', '{'},
            {']', '['},
            {')', '('}
        };

        if (s.size() % 2 == 1) {
            return false;
        }
        for (char ch : s) {
            if (pairs.count(ch)) {
                if (mystack.empty() || mystack.top() != pairs[ch]){
                    return false;
                }
                mystack.pop();
            } else {
                mystack.push(ch);
            }
        }
        return mystack.empty();
    }
};

leetcode 22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:

输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

示例 2:

输入:n = 1
输出:["()"]

分析:此题要输出正常的括号,所以输出的字符串中截止到任意一位置,左括号数一定是大于等于右括号数的。

class Solution {
public:
    void gen(vector<string> & result, string str, int left, int right) {

        if (left == 0 && right == 0) {
            result.push_back(str);
            return;
        }
        if (left > 0) {
            gen(result, str + "(", left - 1, right);
        }
        if (left < right && right > 0) {
            gen(result, str + ")", left, right - 1);
        }
    }
    vector<string> generateParenthesis(int n) {
        vector<string> result;
        gen(result, "", n, n);
        return result;
    }
};

32. 最长有效括号

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

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

解释:最长有效括号子串是 “()”

示例 2:

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

解释:最长有效括号子串是 “()()”

示例 3:

输入:s = ""
输出:0

分析:此题需要借助动态规划,dp[n] 表示截止当前n位置最长有效括号子串长度

class Solution {
public:
    int longestValidParentheses(string s) {
        int maxlen = 0;
        int n = s.size();
        if (n == 0) {
            return maxlen;
        }
        vector<int> dp(n, 0);
        for (int i = 1; i < n; ++i) {
            if (s[i] == ')') {
                if (s[i - 1] == '(') {
                    dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
                }
                else if (i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] -1] == '(') {
                    dp[i] = 2 + dp[i-1] + ((i - dp[i-1]) >= 2? dp[i - dp[i - 1] -2] : 0);
                }

            }
            if (dp[i] > maxlen) {
                maxlen = dp[i] ;
            }
        }
        return maxlen;


    }
};

301.删除无效的括号

删除最小数量的无效括号,使得输入的字符串有效,返回所有可能的结果。

说明: 输入可能包含了除 ( 和 ) 以外的字符。

示例 1:

输入: "()())()"
输出: ["()()()", "(())()"]

示例 2:

输入: "(a)())()"
输出: ["(a)()()", "(a())()"]

示例 3:

输入: ")("
输出: [""]

分析:
方法一:采用回溯的思想,每个位置分别考虑删除以及保留的情况。
方法二:采用BFS,一层层的找。

class Solution {
private:
    int length ;
    vector<string> result;
    string str;
public:
    vector<string> removeInvalidParentheses(string s) {
        int leftRemove = 0;
        int rigthRemove = 0;
        length = s.size();
        str = s;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '(') {
                leftRemove++;
            } else {
                if(s[i] == ')') {
                    if (leftRemove > 0) {
                        leftRemove--;
                    } else {
                        rigthRemove++;
                    }
                }
            }
        }
        dfs(0, 0, 0, leftRemove, rigthRemove, "");
        return result;

    }
    void dfs(int index, int leftCount, int rightCount, int leftRemove, int rightRemove, string path) {
        if (index == length) {
            if (leftRemove == 0 && rightRemove ==0) {
                vector<string>::iterator it;
                it = find(result.begin(), result.end(), path);
                if( it == result.end() ) // finded 
                {
                    result.push_back(path);        
                }              
            }
            return;
        }
         可能的操作 1:删除当前遍历到的字符
        if(str[index] == '(' && leftRemove > 0) {
            //leftRemove > 0,并且当前遇到的是左括号,可以尝试删除当前遇到的左括号

            dfs(index + 1, leftCount, rightCount, leftRemove - 1, rightRemove, path);
        }
        if (str[index] == ')' && rightRemove > 0) {
            //ightRemove > 0,并且当前遇到的是右括号,因此可以尝试删除当前遇到的右括号

            dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove - 1, path);
        }
         可能的操作 2:保留当前遍历到的字符
        path.push_back(str[index]);
        if (str[index] != '(' && str[index] != ')') {
            dfs(index + 1, leftCount, rightCount, leftRemove, rightRemove, path);
        } else if (str[index] == '(') {
            // 考虑左括号
            dfs(index + 1, leftCount + 1, rightCount, leftRemove, rightRemove, path);
        } else if (rightCount < leftCount) {
            // 考虑右括号
            dfs(index + 1, leftCount, rightCount + 1, leftRemove, rightRemove, path);
        }
        path.erase(path.size() - 1);
    }
};
class Solution {
public:
    bool isValid(string s) {
        int leftCount = 0;
        for(char ch : s) {
            if(ch == '(') {
                leftCount++;
            } else if (ch == ')') {
                leftCount--;
            }
            if(leftCount < 0) {
                return false;
            }
        }
        return leftCount == 0;
    }
    vector<string> removeInvalidParentheses(string s) {
        vector<string> result;
        if(s.size() == 0) {
            return {""};
        }
        if(isValid(s)) {
            return {s};
        }
        queue<string> q;
        unordered_set<string> lookup; // 是否被访问过
        q.push(s);
        lookup.insert(s);
        while(!q.empty()) {
            int n = q.size();
            for (int i = 0; i < n; ++i) {
                string str = q.front();
                q.pop();
                for (int j = 0; j < str.size(); ++j) {

                    if (str[j] != '(' && str[j] != ')') {
                        continue;
                    }
                    string temp = str;
                    string str1 = temp.erase(j, 1);
                    if(isValid(str1) && lookup.count(str1) == 0) {
                        vector<string>::iterator it;
                        it = find(result.begin(), result.end(), str1);
                        if(it == result.end()) {
                            result.push_back(str1);
                        }                   
                    } else {
                        if(lookup.count(str1) == 0) {
                            q.push(str1);                       
                        } 
                    }
                    lookup.insert(str1);
                }
            }
            if(result.size() != 0) {
                return result;
            }
        }
        return result;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值