Longest Valid Parentheses [Leetcode]

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来处理,因为之前用stack来判断过括号是否匹配,按子串长度从n逐步减少到1的过程来查找,第一次找到的括号匹配子串即最长的子串,然而想想当问题规模很大而且又没有括号匹配子串时,它的时间复杂度是相当大的,故此方法舍之。

第二想法就是利用动态规划,自底向上来解这个问题。可以很容易地看出它的最优子结构,假设S是括号匹配的,则(S),()S,S(),也是括号匹配的。用布尔型二维数组isValid[i][j]来表示i~j的串是否是匹配的,初始化isValid[i][i+1],然后自底向上求解。这个方法上面的方法的复杂度好了很多,但是还是没有AC掉 TAT。

之后就是看了别人的解法才AC了这道题。

动态规划(个人解法)


复杂度

时间 O(N^2) 空间 O(N^2)

思路

如上

代码

    public static int longestValidParentheses(String s) {
        if(s==null || s.length()<2){
            return 0;
        }
        int len = s.length();
        boolean[][] isValid = new boolean[len][len];
        int max = 0;
        /*初始化*/
        for(int i=0; i

动态规划(别人家的解法)


复杂度

时间 O(N) 空间 O(N)

思路

动态规划法将大问题化为小问题,我们不一定要一下子计算出整个字符串中最长括号对,我们可以先从后向前,一点一点计算。假设d[i]是从下标i开始到字符串结尾最长括号对长度,s[i]是字符串下标为i的括号。如果s[i-1]是左括号,如果i + d[i] + 1是右括号的话,那d[i-1] = d[i] + 1。如果不是则为0。如果s[i-1]是右括号,因为不可能有右括号开头的括号对,所以d[i-1] = 0。

代码

    public static int longestValidParentheses(String s){
        if(s==null || s.length()<2){
            return 0;
        }
        int len = s.length();
        int[] dp = new int[len];
        int max = 0;
        for(int i=0; i-1; i--){
            if(s.charAt(i) == '('){
                int j=i+1+dp[i+1];
                if(j < len && s.charAt(j) == ')'){
                    dp[i] = dp[i+1]+2;
                    if(j+1 < len)
                        dp[i] += dp[j];
                    if(dp[i] > max){
                        max = dp[i];
                    }
                }
            }
        }
        return max;
    }

栈法 Stack(别人家的Stack解法)


复杂度

时间 O(N) 空间 O(N)

思路

用Stack的方法本质上和Valid Parentheses是一样的,一个右括号能消去Stack顶上的一个左括号。不同的是,为了能够计算括号对的长度我们还需要记录括号们的下标。这样在弹出一个左括号后,我们可以根据当前坐标减去栈中上一个(也就是Pop过后的Top元素)的坐标来得到该有效括号对的长度。

代码

     public class Solution {
      public int longestValidParentheses(String s) {
        Stack stk = new Stack();
        int maxLen = 0;
        for(int i = 0; i < s.length(); i++){
            //遇到左括号,将其push进栈
            if(s.charAt(i)=='('){
                stk.push(new Parenthese(i, '('));
            } else {
           //遇到右括号,分类讨论
               //如果当前栈顶是左括号,则消去并计算长度
                if(!stk.isEmpty() && stk.peek().symb=='('){
                    int curLen = 0;
                    stk.pop();
                    if(stk.isEmpty()){
                        curLen = i + 1;
                    } else {
                        curLen = i - stk.peek().indx;
                    }
                    maxLen = Math.max(maxLen, curLen);
                } else {
               //如果栈顶是右括号或者是空栈,则将右括号也push进栈,它的坐标将方便之后计算长度
                    stk.push(new Parenthese(i, ')'));
                }
            }
        }
        return maxLen;
    }
    
    public class Parenthese {
        int indx;
        char symb;
        public Parenthese (int i, char s){
            this.indx = i;
            this.symb = s;
        }
    }

参考资料

Longest Valid Parentheses

你可能感兴趣的:(Longest Valid Parentheses [Leetcode])