题目;
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.
一看到这种括号匹配的题目,就想到用堆栈,压入“(”,遇到“)”就弹出。但是这题并不是要求检查括号是否匹配,而是找出最长的匹配的子串
观察出现不匹配的几种情况:
1、在堆栈为空时遇到“)”,这种情况说明包含这个字符在内的子串是不可能满足题目要求的,于是它可以作为字符串的一个分割点,分别找到他前面和后面的最长匹配子串做比较即可。
2、字符串完结时堆栈中还有“(”,这表示有“(”没有得到匹配,例如(()(),这个时候第一个“(”也是一个分隔符。
接下来我们观察())()(()()((),发现整个字符串被分割为4部分,我们需要计算这四部分的长度,找出最长的一个。
于是我们可以把“(”的下表作为压入堆栈的值,而并非“(”本身,这样在遇到第2种情况时,只需计算堆栈中每个元素之间的差值就可以知道子串的长度了。另外,对于栈底的元素,应该和最近的一个多余“)”的位置做比较,这样就可以统计出第一个没有得到匹配的“(”之前合法的字长长度。而对于栈顶的元素,至于计算字符串末尾和栈顶元素的差就可知道最后一个失配的“(”后面还有多长的合法字符串了。
当遇到第1种情况时,我们也至于要计算这个“)”与上一个失配的“)”之间的距离即可。
代码如下:
import java.util.Stack;
public class No31_LongestValidParentheses {
public static void main(String[] args){
System.out.println(longestValidParentheses(")()(()))))"));
}
public static int longestValidParentheses(String s) {
Stack<Integer> stk = new Stack<Integer>();
int startPos = -1;
int ret = 0;
int result = 0;
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c == '(')
stk.push(i);
else if(c == ')'){
if(stk.empty()){
startPos = i;
result = result>=2*ret?result:2*ret;
ret = 0;
continue;
}
else if(!stk.empty()){
stk.pop();
ret++;
}
}
}
if(stk.empty())
return result>=2*ret?result:2*ret;
int endPos = s.length();
while(!stk.empty()){
int t = stk.pop();
result = result>(endPos-1-t)?result:endPos-1-t;
endPos = t;
}
result = result>(endPos-1-startPos)?result:endPos-1-startPos;
return result;
}
}