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 }

 

你可能感兴趣的:(long)