[leetcode]Longest Valid Parentheses

Longest Valid Parentheses

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 :dp,感觉这道题略坑爹啊,还是屡一下思路吧,毕竟对DP完全不熟悉。

维护一个s.length()一维数组,dp,其中dp[i]表示从索引i到末尾所组成字符串的前缀最长的有效括号组合的长度

例如:)(),则为0,而非2;())(),为2,表示的是前面的()

因此:dp[s.length() - 1] = 0;从后向前逆向求解dp[i],

  1. 如果s[i]=')',则显然dp[i]=0;(均不合法)
  2. 如果s[i]='(',跳过dp[i+1]这段长度从j=i+1+dp[i+1]开始(找到最长前缀的后驱),如果j没越界并且s[j]=')',正好和s[i]匹配(组成了dp[i]的合法最长前缀),则dp[i]=dp[i+1]+2;另外此时可能j之后的也可以连上,所以,可能要加上dp[j+1];

代码如下:

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         if(s == null || s.length() < 2) return 0;
 4         int max = 0;
 5         int[] dp = new int[s.length()];
 6         dp[s.length() - 1] = 0;
 7         for(int i = s.length() - 2; i >= 0; i--){
 8             if(s.charAt(i) == '('){
 9                 int j = i + 1 + dp[i + 1];
10                 if(j < s.length() && s.charAt(j) == ')'){
11                     dp[i] = dp[i + 1] + 2;
12                 if(j + 1 < s.length()){
13                     dp[i] += dp[j + 1];
14                 }
15                 }
16             }
17             max = Math.max(max,dp[i]);
18         }
19         return max;
20     }
21 }
View Code

思路2: 这个思路有点吊,算法具体思想是,先把所有匹配的括号对,变成一样的标记,比如‘0’,例如:)()()()(()变成)000000(00,这样再求是不是容易多了?方法很巧妙,可惜时间复杂度略高,达到了O(n*n)

代码如下:

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         if(s == null || s.length() < 2) return 0;
 4         char[] charArray = s.toCharArray();
 5         for(int i = 0; i < s.length(); i++){
 6             char c = charArray[i];
 7             if(c == ')'){
 8                 for(int j = i - 1; j >= 0; j--){
 9                     if(charArray[j] == '0') continue;
10                     if(charArray[j] == '('){
11                         charArray[i] = charArray[j] = '0';
12                     }
13                         break;
14                 }
15             }
16         }
17         int max = 0;
18         for(int i = 0; i < s.length(); i++){
19             if(charArray[i] == '0'){
20                 int begin = i;
21                 while(i < charArray.length && charArray[i] == '0') i++;
22                 max = Math.max(max,i - begin);
23             }
24         }
25         return max;
26     }
27 }

第二遍记录:

同样采用了DP。

与上面的思路1恰恰相反:这里将dp[i]表示以s[i]为结尾的字符串的后缀的最长合法长度;

状态转移方程:(为了方便,假设下面的指针都是合法的)

1. 当s[i] = '(' 时,显然不需要处理,dp[i] = 0

2. 当s[i] = ')' 时,此时s[i - 1] 有两种情况

2.1 s[i - 1] = '('。表示s[i]匹配成功,要验证dp[i - 2]的状态,以判断是否可以与前面的相连

2.2 s[i - 1] = ')'。表示s[i]并不一定能匹配成功,要验证dp[i - dp[i - 1] - 2] 的状态。

其实这个思路不需要看的,跟上面的思路1一样。有兴趣可以看下:

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         if(s == null || s.length() < 2) return 0;
 4         int max = 0,length = s.length();
 5         char[] sc = s.toCharArray();
 6         int[] dp = new int[length];
 7         Stack<Character> stack = new Stack<Character>();
 8         for(int i = 1; i < length; i++){
 9             if(sc[i] == '(') continue;
10             if(sc[i - 1] == '('){
11                 dp[i] = 2;
12                 if(i - 2 >= 0) dp[i] += dp[i - 2];
13             }else{
14                 if(dp[i - 1] > 0){
15                     int leap = dp[i - 1];
16                     if(i - 1 - leap >= 0 && sc[i - 1 - leap] == '('){
17                         dp[i] = dp[i - 1] + 2;
18                         if(i - leap - 2 >= 0) dp[i] += dp[i - leap - 2];
19                     }
20                 }
21             }
22             max = Math.max(max,dp[i]);
23         }
24         return max;
25     }
26 }
View Code
原文地址:https://www.cnblogs.com/huntfor/p/3886111.html