Leetcode32. Longest Valid Parentheses

关键字:DP,

首先想到的肯定是暴力解法,对每个可能的子字符串进行合法判断,每个子字符串O(n^2),合法判断O(n),加起来O(n^3)。可怕。

就不写了。然后咋改进呢?

自己想到过DP,但是想了想子问题划分,想成了二维dp,没想好怎么划分,就放弃了。

结果看Solution,也是DP。

一维DP,dp[i]表示以i字符结尾的最大Valid Parentheses。

具体看Solution   https://leetcode.com/problems/longest-valid-parentheses/solution/

class Solution {
    public int longestValidParentheses(String s) {
        if(s==null||s.length()==0) return 0;
        int[] dp = new int[s.length()];
        dp[0] = 0;int max = dp[0];
        for(int i=1;i<s.length();i++) {
            if(s.charAt(i)=='(') dp[i]=0;
            else {
                if(s.charAt(i-1)=='(') dp[i]=(i-2>=0?dp[i-2]:0)+2;
                else {
                    if(i-dp[i-1]-1>=0&&s.charAt(i-dp[i-1]-1)=='(') 
                        dp[i]=dp[i-1]+2+(i-dp[i-1]-2>=0?dp[i-dp[i-1]-2]:0);
                    else dp[i]=0;
                }
            }
            max = Math.max(max, dp[i]);
        }  
        return max;
    }
}

15ms,57.44%,第二个波峰。

然后是一个用栈的做法,因为括号匹配问题很容易想到栈。思路如下:

每次见到一个(,就将他的index入栈,见到一个),就出栈一个元素,直到栈里没有(,则这是这个子字符串的 Longest Valid Parentheses。

然后开始对比下个子字符串即可。

中间涉及到计算长度,所以需要开始push进栈一个-1,后面则push进栈该子字符串的最后一位的index,这样可以通过新子字符串最后一位index和上一个的最后一位index相减算出当前局部max。

具体见代码:

class Solution {
    public int longestValidParentheses(String s) {
        int max = 0;
        Stack<Integer> stack = new Stack<>();
        stack.push(-1);
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)=='('){
                stack.push(i);
            }
            else{
                stack.pop();
                if(stack.empty()){
                    stack.push(i);
                }else{
                    max = Math.max(max,i-stack.peek());
                }
            }
        }
        return max;
    }
}

24ms,15.98%.

虽然很慢,但是做出来了是吧。

看了7ms答案,是dp算法的优化版本:

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

思路简化为:仍然是一维DP,简化为有一个虚拟栈的感觉,见到‘(’,虚拟栈多一个元素,只要虚拟栈里有东西,见到‘)’就可以相对dp[i-1]加2。(这里不是dp[i-2]因为前面一个元素也可以是右括号)加2后再对前面的特殊情况做处理。

dp和stack都会即可。如果有空可以看看最快答案,或者试试数组代替stack。

posted @ 2018-12-26 12:46  大胖子球花  阅读(96)  评论(0)    收藏  举报