第51题 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.

Hide Tags
  Dynamic Programming String






Solution in Java using DP 1:
<span style="font-size:18px;">public class Solution {
    public int longestValidParentheses(String s) {
        if(s==null||s.length()<2) return 0;
        
        int[] opj  = new int[s.length()]; 
        //opj[i] denotes the maximum length of the valid substring from 0 to i, <span style="color:#ff0000;"><strong>containing s[i]!!!</strong></span>
        //so we have:
        opj[0] = 0;
        int max = 0;
        
        for(int i=1; i<s.length(); i++){
            if(s.charAt(i)==')'){
                int leftIndex = i - opj[i-1] -1;
                //leftIndex is the index of the matching '(' if it exists.
                if(leftIndex>=0&&s.charAt(leftIndex)=='('){
                    opj[i] = opj[i-1] + 2;
                    if(leftIndex>=2)    opj[i]+=opj[leftIndex-1];
                }
            }
            max = Math.max(opj[i], max);
            
        }
        return max;
        
        
    }
}</span>

Note:注意opj[i]记录s[0...i]中最长的合法子字符串,但该字符串一定包含s[i]!就是说这个子串在s[0...i]中一定是靠右的!!而leftIndex则为该字串的左边界,所以opj[i]记录的最长子串为:s[leftIndex...i],并且s[leftIndex...i]必然形成了一个闭合的括号,即有"(...)"的形式。

Solution in Java using DP 2 (从右往左的DP):
public class Solution {
    public int longestValidParentheses(String s) {
        if(s==null||s.length()<2) return 0;
        int len = s.length();
        int[] opj  = new int[len]; 
        //opj[i] denotes the maximum length of the valid substring from i to len-1, 
        //containing s[i]!!! So we have:
        opj[len-1] = 0;
        int max = 0;
        
        for(int i=len-2; i>=0; i--){
            if(s.charAt(i)=='('){
                int rightIndex = i+ opj[i+1] + 1;
                //rightIndex is the index of the matching ')' if it exists.
                if(rightIndex<len&&s.charAt(rightIndex)==')'){
                    opj[i] = opj[i+1] + 2;
                    if(rightIndex<len-2)    opj[i]+=opj[rightIndex+1];
                }
            }
            max = Math.max(opj[i], max);
            
        }
        return max;
        
        
    }
}

Note: 从右往左算,则对opj[i],其记录的最长有效子串是在s[i...len-1]中靠左的子串,该子串必须包含s[i]。rightIndex为该子串的右边界。
Solution in Java using DP 3 (DP with a little modification):
public class Solution {
    public int longestValidParentheses(String s) {
        if(s==null||s.length()<2) return 0;
        int len = s.length();
        int[] opj  = new int[len]; 
        //opj[i] denotes the maximum length of the valid substring from i to len-1, 
        //containing s[i]!!! So we have:
        opj[len-1] = 0;
        int max = 0, valid=0;   
        //using valid to record if there is a matching ')' for a '('
        //for each ')', valid++;  for each '(', if valid>0 then this '(' is valid, and valid--;
        
        for(int i=len-1; i>=0; i--){
            if(s.charAt(i)=='('&&valid>0){
                opj[i]  = 2 + opj[i+1] + (i+opj[i+1]+1<len-2?opj[i+opj[i+1]+1+1]:0);
                valid--;
            }
            else if(s.charAt(i)==')')   valid++;
            max = Math.max(opj[i], max);
            
        }
        return max;
        
        
    }
}

Solution in Java using a stack and a boolean array:
public class Solution {
    public int longestValidParentheses(String s) {
        if(s==null||s.length()<2) return 0;
        boolean[] valid = new boolean[s.length()];
        Stack<Integer> indices = new Stack<Integer>();
        
        for(int i=0; i<s.length(); i++){
            if(s.charAt(i)=='(')    indices.push(i);
            if(s.charAt(i)==')'&&!indices.empty()){
                valid[i] = true;
                valid[indices.pop()]=true;
            }
        }
        
        int max=0, len = 0;
        for(int i=0; i<s.length();i++){
            if(valid[i])    len++;
            if(!valid[i]||i==s.length()-1)   {
                max = Math.max(max, len);
                len=0;
            }
        }
        return max;
        
        
    }
}

Note: 
很多人会说这道题用动规,可是用动规每次匹配后还要向前到上一个匹配跟这个匹配是否连接,时间复杂度为O(n^2),其实可以换个想法,用一个bool数组来标记已经匹配过的字符,找到最长的连续标记的长度就是所求的结果。只要遍历两遍数组,时间复杂度为O(n)。(last note is referenced from: http://www.cnblogs.com/easonliu/p/3637429.html)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值