leetcode32.最长有效括号

1.栈方法

参考:
https://leetcode.com/problems/longest-valid-parentheses/discuss/14147/My-simple-8ms-C%2B%2B-code (太厉害了)

class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> stk;  //栈里存放的是元素的下标
        stk.push(-1);  
        int maxL=0;  //记录最长有效括号长度
        for(int i=0;i<s.size();i++)  //依次遍历
        {
            int t=stk.top();
            if(t!=-1&&s[i]==')'&&s[t]=='(')  //当前元素是右括号,栈顶元素是左括号时出栈(前面加t!=-1保证栈里有元素)
            {
                stk.pop();  //找到了一个有效的括号组合(可能没有完全覆盖,比如(()),如果当前到第三步,则找的是(),此时栈内还有一个()
                maxL=max(maxL,i-stk.top()); //出栈就更新最大长度,stk.top保存的是与当前右括号匹配的左括号的前一个元素下标
            }
            else
                stk.push(i); //其他情况就入栈
        }
        return maxL;
    }
};

可以用例子)()())()带入跑一下
栈对应的元素变化以及maxL的变化情况如下:

stack		maxL
)			——0
)(			——0
)			——2-0=2
)(			——2
)			——4-0=4
))			——4
))(			——4
))			——max(4,7-5=2=	2

自己如果不是太理解这个方法可以先背下来,核心是如果当前元素是右括号,且栈顶元素是左括号则出栈并更新最大长度(这里最大长度=当前下标-栈顶元素对应的下标),其他情况入栈。

2.动态规划方法
参考:
https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack

longest[i] 表示以第i个字符结尾的最大括号子串长度

1.如果 s[i] == '(',那么longest[i]=0,因为有效的括号总是以右括号结尾的

2.如果 s[i] == ')':1)如果s[i-1] == '(',即它的前一位是左括号,那么就可以和他匹配,
		    则longest[i]=longest[i-2]+22)如果 s[i-1] == ')' 且 s[i-longest[i-1]-1] == '(', 即前一位是右括号,且和s[i]右括
		   号相对应的那个位置是左括号(longest[i-1]表示i-1位置结尾的那个有效括号子串的长度,那么
		   在i-1结尾的括号子串的前一个元素就应该是和第i位配对的元素)
		   那么longest[i] = longest[i-1] + 2 + longest[i-longest[i-1]-2]
		   longest[i-1]表示以i-1结尾的对应的有效括号子串,2表示考虑了第i位和之前与i配对成功的那
		   位的长度,longest[i-longest[i-1]-2]表示与i配对成功的那个位置紧挨着的前一位也有可能存
		   在有效括号子串,应该加上它
例如:"()(())", at i = 5, longest array is [0,2,0,0,2,0], 
longest[5] = longest[4] + 2 + longest[1] = 6.
与第5位对应的应该是第2位
longest[4]表示第3-4的括号子串,2表示加上第2位和第5位,longest[1]表示在第2位紧挨着之前还有有效的括号第0-1位,也应该加上它

代码如下:

int longestValidParentheses(string s) {
            if(s.length() <= 1) return 0;
            int curMax = 0;
            vector<int> longest(s.size(),0);
            for(int i=1; i < s.length(); i++){
                if(s[i] == ')'){
                    if(s[i-1] == '('){
                        longest[i] = (i-2) >= 0 ? (longest[i-2] + 2) : 2;
                        curMax = max(longest[i],curMax);
                    }
                    else{ // if s[i-1] == ')', combine the previous length.
                        if(i-longest[i-1]-1 >= 0 && s[i-longest[i-1]-1] == '('){
                            longest[i] = longest[i-1] + 2 + ((i-longest[i-1]-2 >= 0)?longest[i-longest[i-1]-2]:0);
                            curMax = max(longest[i],curMax);
                        }
                    }
                }
                //else if s[i] == '(', skip it, because longest[i] must be 0
            }
            return curMax;
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值