题目描述:
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; } }