题目描述:
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.
然后换一个思路:
一维简单动态规划,思想是:对S中从后向前的每个 ' ( ' ,我们来计算它最远对应到的那个‘)’的位置,在这两个字符中间的字符能够组成一个合法的括号串。
记当前 '(' 的下标为 i ,用idx[] 来保存每个i的最右合法匹配位置:
1. 如果它的右边是 ' ) ',那明显最远的合法匹配位置就到这个‘)’为止,idx[i] = i+1;
2.如果它的右边是 ' ( ',因为我们已经计算过它的最右合法匹配位置,在接着这个最右位置继续向右找 ;
3.如果右边不是 ‘( )’,则没有合法的匹配位置, idx = -1 ;
例子: 比如 s = " ( ) ( ( ( ) ) "
序号 0 1 2 3 4 5 6 7
( ) ( ( ( ( ) )
现在来计算idx的值;
1.从右向左找到第一个 ‘ ( ’,序号为5,右边是 ‘)’,匹配,所以 idx[ 5 ] = 6;
2.第二个s[4] ,右边是'(' ,它的匹配是6,所以跳到6再看右边,是‘)’,匹配,所以 idx[ 4 ] = 7;
3. 第三个s[3],右边是 '( " ,它的匹配是7,跳到7再看右边,越界,没有匹配,所以idx[3] = -1;
4.第四个s[2] ,右边是‘(’,但右边的‘(‘的idx为-1,即没有合法的匹配,所以s[2]自然也不能向右有合法匹配,idx[2]=-1;
5. s[0] = 1;
所以得到 idx 数组 :
序号 0 1 2 3 4 5 6 7
( ) ( ( ( ( ) )
idx 1 -1 -1 -1 7 6 -1 -1
得到 idx 数组之后,再来计算最大长度,碰到不是-1的就一直往它对应的右括号走,一直累加,碰到-1就计算前面的值,当然最后在最外层还要计算一次,代码如下:
public class Solution {
public int longestValidParentheses(String s){
int n=s.length();
int longest=0;
int[] idx=new int[n];
looper:for(int i=n-1;i>=0;i--){
if(s.charAt(i)==')')
idx[i]=-1;
if(s.charAt(i)=='('){
if(i==n-1){
idx[i]=-1;
}else{
if(s.charAt(i+1)==')')
idx[i]=i+1;
else{
int j=i+1;
while(s.charAt(j)=='('){
int index=idx[j];
if(index==-1){
idx[i]=-1;
continue looper;
}
j=index+1;
if(j==n){
idx[i]=-1;
continue looper;
}
}
idx[i]=j;
}
}
}
}
int cur=0;
for(int i=0;i<s.length();){
if (idx[i]==-1)
{
longest=Integer.max(longest,cur);
cur=0;
i++;
}
else
{
cur+=idx[i]-i+1;
i=idx[i]+1;
}
}
longest=Integer.max(longest,cur);
return longest;
}
}
还有2个简单的方法:
一种来回两次遍历字符串,让多余的全部都变成"#"。
如"()()))((()(())(()))((())(()()()()()()(((((())))))())()())()(())(())())))))(())()((((((((()()(())))))())())))()(((()())()))(((()()((((("
变成:"()()##((()(())(()))((())(()()()()()()(((((())))))())()())()(())(())())####(())()((((((((()()(())))))())())))()(((()())()))###()()#####"
代码如下:
public class Solution {
public int longestValidParentheses(String s) {
char[] c = s.toCharArray();
int len = c.length, t = 0, ans = 0;
for (int i = 0, y = 0; i < len; i++){
if (c[i] == '(')
y++;
else if (c[i] == ')' && --y < 0) {
y = 0;
c[i] = '#';
}
}
for (int i = len - 1, y = 0; i >= 0; i--) {
if (c[i] == ')')
y++;
else if (c[i] == '(' && --y < 0) {
y = 0;
c[i] = '#';
}
t = (c[i] == '#') ? 0 : t + 1;
ans = Math.max(ans, t);
}
System.out.println(new String(c));
return ans;
}
}
另一种用栈:
public class Solution {
public int longestValidParentheses(String s) {
int max=0,start=0;
Stack<Integer> stack=new Stack<Integer>();
int[] a=new int[s.length()];
char[] c=s.toCharArray();
for(int i=0;i<c.length;i++){
if(c[i]=='(') stack.push(i);
else if(!stack.empty()){
start=stack.pop();
a[i]=i-start+1;
if(start>1) a[i]+=a[start-1];
max=Math.max(max,a[i]);
}
}
return max;
}
}