1 , 用Stack
常见的匹配情况有这几种:
X(()(()))XXXX
X((()))XXX
X()()()XXX
具体思路就是在Stack中保存相应字符(主要是左括号)的下标,如果遇到右括号,
就pop出与之对应的左括号下标 i,并且计算出当前最大的有效括号的值,如果遇到
连续多个右括号时,就不断通过pop push操作保证stack中不为空。
只要保证当前操作中stack顶端为能匹配成有效括号的最左一个括号下标或者
是该左括号左侧一个多余的右括号。
AC 13ms:
class Solution {
public int longestValidParentheses(String s) {
int count=0;
if(s==null||s.length()==0)
return count;
Stack<Integer> sk=new Stack();
sk.push(-1);
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='(')
sk.push(i);
else{
sk.pop();
if(sk.isEmpty())
sk.push(i);
else{
count=Math.max(count,i-sk.peek());
}
}
}
return count;
}
}
2 . 左右遍历
分别从左 从右遍历,找出left==right的长度,
可以避免出现这种情况((())和(()))下的误判。
AC 8ms:
class Solution {
public int longestValidParentheses(String s) {
int left=0,right=0,max=0;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='(')
left++;
else
right++;
if(left==right)
max=Math.max(max,2*right);
else if(right>left)
left=right=0;
}
left=right=0;
for(int i=s.length()-1;i>=0;i--){
if(s.charAt(i)==')')
right++;
else
left++;
if(right==left)
max=Math.max(max,2*left);
else if(left>right)
left=right=0;
}
return max;
}
}
3 . DP
假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。
dp[i]表示从s[i]到s[s.length - 1]包含s[i]的最长的有效匹配括号子串长度。则存在如下关系:
- dp[s.length - 1] = 0;
- i从n - 2 -> 0逆向求dp[],并记录其最大值。若s[i] == '(',则在s中从i开始到s.length - 1计算dp[i]的值。
- 这个计算分为两步,通过dp[i + 1]进行的(注意dp[i + 1]已经在上一步求解):
- (1)在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,
- 其下标为j = i + 1 + dp[i + 1]。若j没有越界,并且s[j] == ‘)’,则s[i ... j]为有效括号匹配,dp[i] =dp[i + 1] + 2。
- (2)在求得了s[i ... j]的有效匹配长度之后,若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,
- 即dp[j + 1]。
AC 8ms:
class Solution {
public int longestValidParentheses(String s) {
int max=0;
int[] dp=new int[s.length()];
for(int i=s.length()-2;i>=0;i--){
if(s.charAt(i)=='('){
int j=i+1+dp[i+1];
if(j<s.length()&&s.charAt(j)==')'){
dp[i]=dp[i+1]+2;
if((j+1)<s.length())
dp[i]=dp[i]+dp[j+1];
}
}
max=Math.max(max,dp[i]);
}
return max;
}
}
参考链接: