LeetCode:32. Longest Valid Parentheses

在这里插入图片描述
1.最基本的dp

class Solution {
public:
    int longestValidParentheses(string s) {
        int sz = s.size();
        if (sz == 0)
            return 0;
        vector<vector<bool>> dp(sz, vector<bool>(sz, false));
        int maxLen = 0;
        for (int i = sz-1; i >= 0; --i) 
            for (int j = i; j < sz; ++j) {
                if ((j-i+1) & 0x1) 
                    continue;
                if (s[i] != '(' || s[j] != ')')
                    continue;
                if (j-i+1 == 2) {
                    dp[i][j] = true;
                } else if (dp[i+1][j-1]) {
                    dp[i][j] = true;
                } else {
                    for (int k = i+1; k < j; k += 2)
                        if (dp[i][k] && dp[k+1][j]) {
                            dp[i][j] = true;
                            break;
                        }
                }
                if (dp[i][j] && (j-i+1) > maxLen)
                    maxLen = j-i+1;
                
            }
        return maxLen;
    }
};
//最基本的dp,虽然超时,但是是一个可以用的方法
//思路:
//dp[i][j]:s[i->j]是否有效
//然后首先必须s[i] == '(' && s[j] == ')',然后看大小为2的情况,然后
//1.可能是中间包了有效的括号对,也就是dp[i+1][j-1]
//2.或者分成两段是有效的,也就是那个循环的意思

这个dp是我自己想出来的,但是超时了
2.用栈

class Solution {
public:
    int longestValidParentheses(string s) {
        int sz = s.size();
        if (sz < 2)
            return 0;
        stack<char> sc;
        stack<int> si;
        si.push(-1);//方便计算,而且不可或缺,保证了正确性
        for (int i = 0; i < sz; ++i) {
            if (s[i] == '(') {
                sc.push('(');
                si.push(i);
            } else {
                if (sc.empty() || sc.top() != '(') {
                    sc.push(')');
                    si.push(i);
                } else {
                    sc.pop();
                    si.pop();
                }
            }
        }
        int maxLen = 0;
        int end = sz; 
        while (!si.empty()) {
            int beg = si.top();
            si.pop();
            int len = end - beg - 1;//len有可能是0, 2, 4。。。
            assert(!(len & 0x1));
            maxLen = max(maxLen, len);
            end = beg;
        }
        return maxLen;
    }
};
//做题过程中暴露出自己的问题:自己检查的时候光注意思路的正确了,没有举出corner case,特殊例子,来攻击自己的算法。检查的时候不仅要注意思路方法的正确,而且需要注意多举几个例子的。

//整体思路:类似用栈来验证括号是否正确的那种题目,这里多用了一个栈来保存相应的index,最后留下的下标,它们两两之间的部分说明是有效的括号组合(连续的有效的都被弹出了,留下的是没办法组合的),那么找出中间部分最长的那一个就是符合题意的
//比如:整个长度为10,最后si中留下了2, 9,那么0->1, 3->8是有效的。

整个思路类似用栈来验证括号是否正确的那一类题目的解法。有一些细节需要注意。这个也是自己写的。

3.dp

class Solution {
public:
    int longestValidParentheses(string s) {
        int sz = s.size();
        if (sz < 2)
            return 0;
        vector<int> dp(sz, 0);
        for (int i = 0; i < sz; ++i) {
            if (s[i] == '(')
                continue;
            if (i > 0 && s[i-1] == '(')
                dp[i] = 2 + (i > 1 ? dp[i-2] : 0);
            if (i > 0 && s[i-1] == ')') {
                if (i-1-dp[i-1] >= 0 && s[i-1-dp[i-1]] == '(')
                    dp[i] = dp[i-1] + 2 + (i-2-dp[i-1] >= 0? dp[i-2-dp[i-1]] : 0);//重要的一点是:在这种情况下(s[i]==')', s[i-1]==')'),只能这个if所指使的情况下,dp[i]才可能大于0,因为在i-1前面(包括)dp[i-1]个数字中,都是valid的括号对,不可能出现多一个'('来使s[i]的')'消掉
            }
        }
        return *max_element(dp.begin(), dp.end());
    }
};
//https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack
//dp[i]:以s[i]结尾的最长有效子串
//转移方程看链接吧

这个dp方法是看的讨论区来的。确实比我想的dp要简化的多而且效率要高。看来不能脑袋一热就决定状态为二维的,还是需要多试几个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值