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.
一刷
题解:
- 使用类似valid parentheses的方法。
- 维护一个depth,一个count。
- 从左向右遍历时并且当char == '('时,depth++,否则char = ')',depth--,这时候我们count++,因为找到了一对valid parenthese
- 当depth == 0的时候,左右括号平衡,可以尝试更新max, max = Math.max(max, count * 2)
- 接下来判断depth是否小于0,小于0的话depth = 0, count = 0,我们从头开始计算。
- 左右各自遍历一遍。从右向左遍历是为了计算类似于"()(()()"这种情况,这时depth always > 0,没办法得到max = 4的结论。
- 一种是一维DP,分好几种情况,画一个decision tree会比较清楚逻辑。
- 维护一个数组max[], 其中max[i]代表以s.charAt(i)结尾的longest valid parentheses的长度。我们考虑接下来集中情况。
- max[0] = 0,因为此时不能组成"()"。所以我们可以直接从 i = 1开始遍历
- 当前字符是'(', max[i] = 0,因为valid parentheses不能以'('结尾
否则,当前字符等于')',这时候继续判断几种情况- s.charAt(i - 1) = '(',正好可以组成一对括号。
- 当 i - 2 >= 0,max[i] = max[i - 2] + 2
- 当 i - 2 < 0, max[i] = 2
- 否则s.charAt(i - 1) = ')',此时我们也是继续进行判断
- 此时我们要求出i关于max[i - 1]对称的字符,就是 i - max[i - 1] - 1
假如i - max[i - 1] - 1 >= 0,并且 s.charAt(i - max[i - 1] - 1) == '('
此时表示从i - max[i - 1] - 1到i这一段都合理,所以这一部分等于max[i - 1] + 2, 我们要继续判断 i - max[i - 1] - 2
当i - max[i - 1] - 2 >= 0, 则 max[i] = max[i - 1] + 2 + max[i - max[i - 1] - 2]
否则max[i] = max[i - 1] + 2
否则max[i] = 0,我们不改变什么
- 此时我们要求出i关于max[i - 1]对称的字符,就是 i - max[i - 1] - 1
- s.charAt(i - 1) = '(',正好可以组成一对括号。
- 在开头维护一个res = 0, 每次计算完max[i]之后尝试更新这个res,最后返回的也是这个res.
- 其实还可以继续简化,留给三刷了
第一种方法:
public class Solution {
public int longestValidParentheses(String s) {
if(s == null || s.length()<=1) return 0;
int count = 0, max=0, depth = 0;
for(int i=0; i<s.length(); i++){
char c = s.charAt(i);
if(c == '(') depth++;
else{
depth--;
count++;
if(depth == 0) max = Math.max(max, count*2);
if(depth<0){
depth = 0;
count = 0;
}
}
}
depth = 0;
count = 0;
for(int i=s.length()-1; i>=0; i--){
char c = s.charAt(i);
if(c == ')') depth++;
else{
depth--;
count++;
if(depth == 0) max = Math.max(max, count*2);
if(depth<0){
depth = 0;
count = 0;
}
}
}
return max;
}
}
二刷:
accumulatedLen来积攒matchedLen
Stack
public class Solution {
public int longestValidParentheses(String s) {
if(s == null || s.length() == 0) return 0;
Stack<Integer> stack = new Stack<>();
int maxLen = 0;
int accumulatedLen = 0;
for(int i=0; i<s.length(); i++){
if(s.charAt(i) == '(') stack.push(i);
else{
if(stack.isEmpty()) accumulatedLen = 0;//())()(), )的数目比(多
else{
int matchedLen = i - stack.pop() + 1;
if(stack.isEmpty()){
accumulatedLen += matchedLen;
matchedLen = accumulatedLen;
}
else{//"(()()" ,用i - stack.peek()来得到valid parenthesis个数
matchedLen = i - stack.peek();
}
maxLen = Math.max(maxLen, matchedLen);
}
}
}
return maxLen;
}
}