Leetcode--计算一个字符串中最长的有效括号字符长度

本文介绍了如何解决LeetCode中关于计算一个字符串中最长有效括号字符长度的问题。通过分析括号匹配的思路,提出从'('开始计数,遇到')'时计数器加减,当计数器为零时记录有效长度。对于复杂情况,如'('较多的情况,采用反向遍历的方法以找到最长有效括号子串。

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

Leetcode–计算一个字符串中最长的有效括号字符长度

首先这又是一道括号匹配的问题,我这里先记录一下之前几道类似的题目:
1、给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

思路:首先空串题目认为是有效字符串,这里只需简单判断,给出结果即可;接下来对于一般字符串,我们利用栈的先进后出结构辅助执行判断:遍历字符串,左符号入左栈,右符号与左栈栈顶进行match判断,如果匹配则左栈pop,否则该右符号push右栈,可能看代码会更清晰些:

bool isValid(string s) {
    /*左栈与右栈,左符号入左栈,右符号先与左栈栈顶元素比较,相等左栈顶出栈,否则右栈入栈*/
    /*先定义左符号,右符号组*/
    if(s.size()==0)
        return true;
    
    stack<char> leftStack;
    stack<char> rightStack;
    for(char& c : s){
        if(isLeftSignal(c))
            leftStack.push(c);
        else if(isRightSignal(c)){
            //判断左右栈顶是否相同
            if(leftStack.size()==0 || !isMatch(leftStack.top(),c)) return false;
            else leftStack.pop();
        }
    }
    if(leftStack.size()==0) return true;
    return false;
}
private:
bool isLeftSignal(char c){
        if(c == '{' || c == '[' || c =='(')
            return true;
        else
            return false;
    }
bool isRightSignal(char c){
        if(c == '}' || c == ']' || c ==')')
            return true;
        else
            return false;
    }
bool isMatch(char a, char b){
    if(a == '(' && b == ')')
        return true;
    else if(a=='{' && b=='}')
        return true;
    else if(a=='[' && b==']')
        return true;
    return false;
}

2、给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]

我的一篇博客里有较详细的记录
https://blog.youkuaiyun.com/qq_34606546/article/details/84928073
是回溯法的一种应用

    vector<string> generateParenthesis(int n) {
       /*回溯,添加时限制条件*/ 
       /*回溯的关键:1、终止条件:当前字符串长度==2*n
                   2、括号符合规则的条件:(数小于n时可添加(,‘)’同理*/
        vector<string> ret;
        string str = "";
        backTrack(ret, str, 0, 0, n);
        return ret;
    }
void backTrack(vector<string>& v, string str, int open, int close, int max){
    if(str.size() == 2*max){
        v.push_back(str);
        return;
    }
    if(open < max) 
    {
        str = str+'(';
        backTrack(v, str, open+1, close, max);//第一个一定是'('
        str.pop_back();
    }   
    if(close < open) //)的数量一定小于(的数量
    {
        str = str + ')';
        backTrack(v, str, open, close+1, max);
        str.pop_back();
    }
}

现在来看下这道题:
3、最长有效括号
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 "()()"

leetcode标为了困难,其实倒也没那么难,思路对了还是比较容易的
我们按字符串匹配的思路,首先第一个匹配的一定是 ‘(’,第一个 '('之前的所有 ')'为不匹配部分,不计入匹配个数。在 ‘(‘后,进入一个’(’,计数器加一, ')'计数器减一,遍历字符串的过程中如果计数器为零(完全匹配,记录有效长度),计数器为负(匹配字符结束,计数器清零,重新开始计数)。并注意用max记录最大的有效长度。

int longestValidParentheses(string s) {
         if(s.size()==0) return 0;
         return calc(s,0,1,s.size());
}
int calc(string s, int i, int flag, int end, char c){
    int max = 0, sum = 0, currLen = 0, validLen = 0;
    for(; i!=end; i+=flag){
        sum += s[i]==c? 1:-1;
        currLen++;
        if(sum < 0){
            max = max>validLen? max:validLen;
            sum = 0;
            currLen = 0;
        }
        else if(sum==0){
            validLen = currLen;
        }
    }
    return max>validLen ? max:validLen;
}

注意上述思路有一个问题,那就是如果’('较多,如:"(()()(())",无法给出有效长度,计数器sum总是大于零的,所以这里采用反向遍历:

int longestValidParentheses(string s) {
         if(s.size()==0) return 0;
         return max(calc(s,0,1,s.size(),'('),calc(s,s.size()-1,-1,-1,')'));
    }

int calc(string s, int i, int flag, int end, char c){
    int max = 0, sum = 0, currLen = 0, validLen = 0;
    for(; i!=end; i+=flag){
        sum += s[i]==c? 1:-1;
        currLen++;
        if(sum < 0){
            max = max>validLen? max:validLen;
            sum = 0;
            currLen = 0;
        }
        else if(sum==0){
            validLen = currLen;
        }
    }
    return max>validLen ? max:validLen;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值