LeetCode String 32 Longest Valid Parentheses

12 篇文章 0 订阅
4 篇文章 0 订阅

32. Longest Valid Parentheses

Given a string containing just the characters ‘(’ and ‘)’, find the length of the longest valid (well-formed) parentheses substring.

Example 1:
Input: “(()”
Output: 2
Explanation: The longest valid parentheses substring is “()”

Example 2:
Input: “)()())”
Output: 4
Explanation: The longest valid parentheses substring is “()()”

solution 1 : sliding windows

维护两个ptr, l , r, 从0开始,递增l直到遇到第一个 " ( " "(" "(",然后开始从这个 l 开始滑动 r,直到open和close个数相等,或者close个数超过open个数,终止当前循环,寻找下一个 l 。

    public int longestValidParentheses(String s) {
        if (s.length() <= 1) return 0;
        int l = 0;
        int r = 0;
        int open = 0;
        int res = 0;
        while (l < s.length()) {
            int close = 0;
            while (l < s.length() && s.charAt(l) != '(')
                l++;
            if (l >= s.length()) break;
            r = l + 1;
            open = 1;
            while (r < s.length()) {
                if (s.charAt(r) == '(')
                    open++;
                else
                    close++;
                if (close > open) break;
                if (open == close)
                    res = Math.max(res, r-l+1);
                r++;
            }
            l++;
        }
        return res;
    }

solution 2 : DP

This problem can be solved by using Dynamic Programming. We make use of a dp \text{dp} dp array where iith element of dp \text{dp} dp represents the length of the longest valid substring ending at iith index. We initialize the complete %\text{dp}% array with 0’s. Now, it’s obvious that the valid substrings must end with ‘)’ \text{‘)’} ‘)’. This further leads to the conclusion that the substrings ending with ‘(’ \text{‘(’} ‘(’ will always contain ‘0’ at their corresponding dp \text{dp} dp indices. Thus, we update the dp \text{dp} dp array only when ‘)’ \text{‘)’} ‘)’ is encountered.

To fill dp \text{dp} dp array we will check every two consecutive characters of the string and if

s [ i ] = ‘)’ \text{s}[i] =\text{‘)’} s[i]=‘)’ and s [ i − 1 ] = ‘(’ \text{s}[i - 1] = \text{‘(’} s[i1]=‘(’, i.e. string looks like . . . . . . . ( ) " ⇒ .......()" \Rightarrow .......()" dp [ i ] = dp [ i − 2 ] + 2 \text{dp}[i]=\text{dp}[i-2]+2 dp[i]=dp[i2]+2

We do so because the ending “()” portion is a valid substring anyhow and leads to an increment of 2 in the length of the just previous valid substring’s length.

s [ i ] = ‘)’ \text{s}[i] = \text{‘)’} s[i]=‘)’ and s [ i − 1 ] = ‘)’ \text{s}[i - 1] = \text{‘)’} s[i1]=‘)’, i.e. string looks like . . . . . . . ) ) " ⇒ .......))" \Rightarrow .......))" if s [ i − dp [ i − 1 ] − 1 ] = ‘(’ \text{s}[i - \text{dp}[i - 1] - 1] = \text{‘(’} s[idp[i1]1]=‘(’ then dp [ i ] = dp [ i − 1 ] + dp [ i − dp [ i − 1 ] − 2 ] + 2 \text{dp}[i]=\text{dp}[i-1]+\text{dp}[i-\text{dp}[i-1]-2]+2 dp[i]=dp[i1]+dp[idp[i1]2]+2

The reason behind this is that if the 2nd last ‘)’ \text{‘)’} ‘)’ was a part of a valid substring (say s u b s sub_s subs), for the last ‘)’ \text{‘)’} ‘)’ to be a part of a larger substring, there must be a corresponding starting ‘(’ \text{‘(’} ‘(’ which lies before the valid substring of which the 2nd last ‘)’ \text{‘)’} ‘)’ is a part (i.e. before s u b s sub_s subs). Thus, if the character before s u b s sub_s subs happens to be ‘(’ \text{‘(’} ‘(’, we update the dp [ i ] \text{dp}[i] dp[i] as an addition of 2 2 2 in the length of s u b s sub_s subs which is dp [ i − 1 ] \text{dp}[i-1] dp[i1]. To this, we also add the length of the valid substring just before the term “(,sub_s,)” , i.e. dp [ i − dp [ i − 1 ] − 2 ] \text{dp}[i-\text{dp}[i-1]-2] dp[idp[i1]2].

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

solution 3 :

In this approach, we make use of two counters leftleft and rightright. First, we start traversing the string from the left towards the right and for every encountered, we increment the leftleft counter and for every ‘)’ \text{‘)’} ‘)’ encountered, we increment the rightright counter. Whenever leftleft becomes equal to rightright, we calculate the length of the current valid string and keep track of maximum length substring found so far. If rightright becomes greater than leftleft we reset leftleft and rightright to 00.

Next, we start traversing the string from right to left and similar procedure is applied.

public class Solution {
    public int longestValidParentheses(String s) {
        int left = 0, right = 0, maxlength = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                maxlength = Math.max(maxlength, 2 * right);
            } else if (right >= left) {
                left = right = 0;
            }
        }
        left = right = 0;
        for (int i = s.length() - 1; i >= 0; i--) {
            if (s.charAt(i) == '(') {
                left++;
            } else {
                right++;
            }
            if (left == right) {
                maxlength = Math.max(maxlength, 2 * left);
            } else if (left >= right) {
                left = right = 0;
            }
        }
        return maxlength;
    }
}

There are only three cases for a string:

  1. ‘(’ are more than ‘)’
  2. ‘(’ are less than ‘)’
  3. ‘(’ and ‘)’ are the same
    Now, when you scan from left to right, you can only find the correct maxLength for cases 2 and 3, because if it is case 1, where ‘(’ \text{‘(’} ‘(’ are more than ‘)’ \text{‘)’} ‘)’ (e.g., "((()" \text{"((()"} "((()"), then left is always greater than right and maxLength does not have the chance to be updated.

Similarly, when you scan from right to left, you can only find the maxLength for cases 1 and 3.
Therefore, a two-pass scan covers all the cases and is guaranteed to find the correct maxLength

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值