【LeetCode】32. Longest Valid Parentheses【栈&动态规划】

       它的标题基本就是题目了,找出连续的最长有效括号的长度,再看一下原题的两个栗子就更明显了,尤其是第二个栗子中的()()部分,更是此题的一个关键,后面还会经常提起。这道题题意相当简单,思路相当简洁,代码相当简短,但是感觉想起来没有那么简单,做完有一种相当巧妙的感觉,所以分享出来。

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

一、动态规划

       搞一个dp数组,dp[i]代表到s[i]截止的最长有效括号长度,那么如果s[i+1]也有效的话,只需dp[i+1] = dp[i]+2(多一对括号),但是这样并不全面,如果这一段的前面紧挨着另一段有效括号的话则需要把他们加上,比如()()的后一对()前面是有效的()所以要加上,())()中间隔了一个非法的)则不用加。具体细节见详细代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int result = 0;
        vector<int> dp(s.size(),0);    //dp数组
        for (int i = 1;i < s.size();i++){
            if (s[i] == ')'){    //如果是')'才有是否有效的判断
                int pos = i-dp[i-1]-1;    //前一段有效括号的前一个括号位置
                if (pos >= 0 && s[pos] == '('){    //如果是'('正好对上
                    dp[i] = dp[i-1]+2;    //加2
                    if (pos-1 > -1)       //如果这一段的前面正好紧挨着另一段有效括号,加在一起
                        dp[i]+=dp[pos-1];
                    result = max(dp[i],result);
                }
            }
        }
        return result;
    }
};

二、栈 

       因为学数据结构的栈的时候书上的例子就是判断()[]{}包含三种括号的表达式是否合法,所以首先想到的是用栈来做。需要借助一个int变量pos记录非法串的结尾,初始为-1,也就是从0开始寻找,遇到'('就把位置i压入栈,遇到'('的时候就弹出一个,如果栈空了没的弹,说明匹配不了,把pos移到这里,表示pos之前的都不用看了,如果栈不空能弹一个,还要看弹完空不空,如果弹完一个空了,说明从pos往后都是合法的(max(result,i-pos)),如果不空则暂时不能下此断言(max(result,i-p.top()))。说白了pos的作用就是处理()()这种情况,想一下如果没有pos,结果就会是2而非4。具体细节见详细代码:

class Solution {
public:
    int longestValidParentheses(string s) {
        int result = 0,pos = -1;    //pos很重要
        stack<int> p;
        for (int i = 0;i < s.size();i++){
            if (s[i] == '(')    //'('压栈,直接下一次循环
                p.push(i);
            else if (p.empty())    //栈里没有'('给')'匹配,此处非法,移动pos到i,之前不用看了            
                pos = i;
            else{
                p.pop();    //如果弹出一个'('栈空了,则从pos往后都合法,如果非空则不能确定
                result = p.empty() ? max(result,i-pos) : max(result,i-p.top());
            }
        }
        return result;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值