一. Longest Valid Parentheses
Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.
For “(()”, the longest valid parentheses substring is “()”, which has length = 2.
Another example is “)()())”, where the longest valid parentheses substring is “()()”, which has length = 4.
Difficulty:Hard
TIME:TIMEOUT
解法一(动态规划)
看到这道题的时候,就想起了求最长回文子序列的问题,不过两道题的解法并不相同。
如果用一个数组表示以括号字符”)”结尾的最长有效括号序列,这道题最优子结构可以描述为,并且用字母s表示输入字符串:
- 如果s[i]==’)’ && s[i - 1]==’(‘,那么dp[i]=dp[i-2]+2;
- 如果s[i]==’)’ && s[i - dp[i-1]-1] ==’(‘,那么dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2];
更直观的表达就是这样:
- 第一种情况可以称之为扩展,比如形如()()。
- 第二种情况可以称之为包含,比如形如(())。
对于有效括号序列来说,要不就是扩展,要不就是包含,没有第三种情况。
int longestValidParentheses(string s) {
if(s.size() < 2)
return 0;
vector<int> dp(s.size(),0); //记录以')'结尾的最长有效括号长度
int len = 0;
for(int i = 1; i < s.size(); i++) {
if(s[i] == ')' && s[i - 1] == '(') //扩展
dp[i] = i - 2 >= 0 ? dp[i - 2] + 2 : 2;
else if(s[i] == ')' && s[i - dp[i - 1] - 1] == '(') //包含
//注意这里包含之后还要再扩展一次
dp[i] = i - dp[i - 1] - 2 >= 0 ? dp[i - 1] + 2 + dp[i - dp[i - 1] - 2] : dp[i - 1] + 2;
len = max(len, dp[i]);
}
return len;
}
代码的时间复杂度为
解法二(贪心算法)
这道题也可以用贪心来求解,不过需要用到栈。分为以下几种情况。
- 当遇到’(‘,将该字符的下标压入栈中
- 当遇到’)’,如果这个时候栈为空,说明字符’)’是多余的,因此字符序列可以从这里断开
- 当遇到’)’,这个时候栈不为空,这个时候就从栈中弹出一个下标,弹出下标之后如果栈为空,说明这个字符序列完全是有效括号序列,如果弹出下标后栈不为空,说明这个字符序列只有部分是有效括号序列,起始位置为栈顶的下标。
int longestValidParentheses(string s) {
if(s.size() < 2)
return 0;
vector<int> v;
int left = -1;
int len = 0;
for(int i = 0; i < s.size(); i++) {
if(s[i] == '(')
v.push_back(i);
else if(v.empty())
left = i;
else {
v.pop_back();
if(v.empty())
len = max(len, i - left); //栈中元素完全匹配
else
len = max(len, i - v.back()); //栈中元素不完全匹配,计算部分长度
}
}
return len;
}
代码的时间复杂度为