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