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.

这个题很典型的使用stack来解即可。


想法是存上每个‘(’之前已经匹配的括号数量。
比如
()(()()(()
第1次遇到前括号,入栈数字是0,然后遇到后括号,现在的长度是2+0
第2次遇到前括号,入栈数字是2,当前长度重设为0
第3次遇到前括号,入栈数字是当前长度0.然后后括号,出栈,长度是2+0,
第4次遇到前括号,入栈数字是当前长度2.然后后括号,出栈,长度是2+2,
第5次遇到前括号,入栈数字是当前长度4,当前长度重设为0
第6次遇到前括号,入栈数字是当前长度0,遇到后括号,出栈,长度是2.
如果栈内仍有数字,目前是2,4,则全部出栈,和当前长度2比。取最长为4.

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         // Start typing your Java solution below
 4         // DO NOT write main() function
 5       Stack<Integer> stack = new Stack<Integer>();
 6       int len = 0;
 7       int maxLen = 0;
 8       for(int i = 0; i < s.length(); ++i) {
 9           if(s.charAt(i) == '(') {
10               stack.push(len);
11               len = 0;
12           } else {
13               if (stack.empty()) {
14                   maxLen = Math.max(maxLen, len);
15                   len = 0;
16               } else {
17                   len = len + 2 + stack.pop();
18               }
19           }
20       }
21       while(!stack.empty()) {
22           maxLen = Math.max(maxLen, stack.pop());
23       }
24       return Math.max(maxLen, len);
25     }
26 }

 DP 解法:

这道题可以用一维动态规划逆向求解。假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。 dp[i]表示从s[i]到s[s.length - 1]最长的有效匹配括号子串长度, 且这个有效匹配括号一定是从i开始的。则存在如下关系:

  • dp[s.length - 1] = 0;
  • 从i - 2 -> 0逆向求dp[],并记录其最大值。若s[i] == '(',则在s中从i开始到s.length - 1计算s[i]的值。这个计算分为两步,通过dp[i + 1]进行的(注意dp[i + 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
    • 在求得了s[i ... j]的有效匹配长度之后,若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1]。
 1 public int longestValidParentheses(String s) {
 2         int n = s.length();
 3         int[] dp = new int[n+1];
 4         int max = 0;
 5         for(int i = n-2; i >= 0; i--) {
 6             if(s.charAt(i) == '(') {
 7                 int j = i+1+dp[i+1];
 8                 if(j < n && s.charAt(j) == ')') {
 9                     dp[i] = 2+dp[i+1]+dp[j+1];
10                     max = Math.max(max, dp[i]);
11                 }
12             }
13         }
14         
15         return max;
16     }

 

第二遍:使用和 Largest Rectangle in Histogram 类似的思想做。 这里有一个问题 就是如果都规约到了栈空的时候该如何存, 即 () () 这种情况, 所以这时候使用一个变量base。 再就是如果出现了)  而栈里已经没有( 该怎么办。 这时其实出来base 没有和max比较 其他都已经比较了, 所以将base 和 max 比较,然后清空全部东西。

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         // Start typing your Java solution below
 4         // DO NOT write main() function
 5         if(s == null || s.length() == 0) return 0;
 6         Stack<Integer> st = new Stack<Integer>();// 栈里存的是已匹配的最长长度
 7         int max = 0;
 8         int base = 0;
 9         for(int i = 0; i < s.length(); i ++){
10             if(s.charAt(i) == '('){
11                 st.push(0);
12             }else if(s.charAt(i) == ')' && !st.isEmpty()){//当是)时 进行匹配,消去当前的这一对。并更新最长长度。
13                 int tmp = st.pop() + 2;
14                 max = tmp > max ? tmp : max;
15                 if(!st.isEmpty()){//栈里还有未配对的(
16                 st.push(tmp + st.pop());
17                 }else{//栈已经空了,更新base
18                     base += tmp;
19                 }
20             }else{// )多了
21                 max = base > max ? base : max;
22                 base = 0;
23                 st = new Stack<Integer>();
24             }
25         }
26         while(!st.isEmpty()){// 查看栈里剩余的那些最长长度, 这些都是没有配对完的。
27             int tmp = st.pop();
28             max = tmp > max ? tmp : max;
29         }
30         max = base > max ? base : max;
31         return max;
32     }
33 }

 第三遍:

先向stack里面放个0 用于都匹配成功的时候存放匹配的个数。

每当遇到( 时, 放一个0, 说明从这个(开始没有匹配成功一对。

每当遇到)时, 如果stack 的 size > 0, 说明还有(没用完,那么进行一次匹配 ==> 将其从stack中取出, 并且将结果加到下一层的(中。

                      如果 size ==1 ,说明之前所有的(都用完了, 所以重置stack。

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         if(s == null || s.length() == 0) return 0;
 4         LinkedList<Integer> ll = new LinkedList<Integer>();
 5         ll.push(0); // this is the bot of the stack(nothing in the stack yet)
 6         int max = 0;
 7         for(int i = 0; i < s.length(); i ++){
 8             if(s.charAt(i) == '(') ll.push(0);
 9             else{
10                 if(ll.size() > 1){
11                     int count = ll.pop();
12                     int sum = count + 1 + ll.pop();
13                     max = max > sum ? max : sum;
14                     ll.push(sum);
15                 }else{
16                     ll.clear();
17                     ll.push(0);
18                 }
19             }
20         }
21         return max * 2;
22     }
23 }

 第四遍:

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         if(s == null || s.length() == 0) return 0;
 4         LinkedList<Integer> stack = new LinkedList<Integer>();
 5         stack.add(0);
 6         int result = 0;
 7         for(int i = 0; i < s.length(); i ++){
 8             if(s.charAt(i) == '(') stack.push(0);
 9             else{
10                 if(stack.size() > 1){
11                     int tmp = stack.pop() + 2;
12                     result = Math.max(result, tmp);
13                     tmp += stack.pop();
14                     stack.push(tmp);
15                 }else{
16                     int tmp = stack.pop();
17                     result = Math.max(result, tmp);
18                     stack.push(0);
19                 }
20             }
21         }
22         while(!stack.isEmpty()){
23             result = Math.max(result, stack.pop());
24         }
25         return result;
26     }
27 }

 

posted on 2013-10-13 09:07  Step-BY-Step  阅读(210)  评论(0编辑  收藏  举报

导航