题目描述
给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
方法一:栈
用栈 p 存储还未匹配的 ( 的下标,flag 用来标记 ( 的位置;
当 s[ i ] 为 ( 时,直接入栈;
当 s[ i ] 为 ) 时,若栈为空,flag = i + 1,前面的都作废,若栈不空,pop( ),匹配 ( ;
匹配后,若栈为空,求长度,res = i - flag + 1;
若栈不空,求长度,res = i - p.top( )(这个下标的 ( 还未出栈,少加 1 )!
class Solution {
public:
int longestValidParentheses(string s) {
int res = 0;
int n = s.size();
stack<int> p;
int flag = 0;
for(int i=0; i<n; i++){
if(s[i] == '('){
p.push(i);
}else{
if(p.empty())
flag = i + 1;
else{
p.pop();
if(p.empty())
res = max(res, i-flag+1);
else
res = max(res, i-p.top());
}
}
}
return res;
}
};
方法二:动态规划
dp[ i ] 表示以 i 下标符号为结尾的最长有效括号长度。
若当前符号为 ' ( ',dp[ i ] 肯定为 0;若当前符号为 ' ) ',则分两种情况:
1)s[i - 1] 为 ' ( ' 时,dp[ i ] = dp[i - 2] + 2;
2)s[i - 1 - dp[i - 1]] 为 ' ( ' 时(跳过 dp[i - 1] 长度找再前一个的符号),dp[ i ] = dp[i - 1] + 2 + dp[ i - 2 - dp[i - 1]],注意不要忘记再前面的 dp[ i - 2 - dp[i - 1]] 可能匹配成功的有效括号长度。
res 保存最大值,每次计算完 dp 后更新最大值。
class Solution {
public:
int longestValidParentheses(string s) {
if(s.empty())
return 0;
int res = 0;
int n = s.size();
vector<int> dp(n,0);
if(s[0] == '(' && s[1] == ')')
dp[1] = 2;
res = max(res,dp[1]);
for(int i=2; i<n; i++){
if(s[i] == '(')
dp[i] = 0;
else{
if(s[i-1] == '(')
dp[i] = dp[i-2] + 2;
else if(s[i-1-dp[i-1]] == '(')
dp[i] = dp[i-1] + 2 + dp[i-2-dp[i-1]];
}
res = max(res,dp[i]);
}
return res;
}
};