leetcode32 求最长有效括号

题目:给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:

输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"

解析:有效的括号子串可以分为两种,一种是()(),一种是((())),针对这两种括号的任意组合,我们可以求出状态转移方程如下,从而用一个一维数组就可以解决

1.初始化子串只有0和1的情况,当只有s[0]等于"("和s[1]等于")"时,dp[0]=0,dp[1]=2,其余情况dp[0]和dp[1]都为0

2.从下标2开始遍历字符串:

(1)如果s[i]="("时,无法判断出长度,因此dp[i]=0,

(2)当s[i]=")"时,

如果s[i-1]="(",则是()()的情况,我们可以用dp[i]=dp[i-2]+2来表示;

如果s[i-1]=")"时则比较复杂,首先我们需要向前滑动s[i-1]的合法子串距离dp[i-1],去找跟下标i对应的i-1-dp[i-1]是否存在(用大于零判断),如果不存在则dp[i] = 0,如果还存在且s[i-1-dp[i-1]]等于"(",再考虑到前面相连的字符串有括号闭合的情况,需要把前面相连的已经闭合的括号的子串都相加,再去判断i-1-dp[i-1]下标前一个位置是否还存在,如果还存在则把dp[i-2-dp[i-1]]+dp[i-1]+2,如果不存在则dp[i-1]+2

 

我们模拟一遍,如下图,先是初始化,初始化完毕后,当程序走到下标3时,因为前一个s[2]等于“(",因此dp[下标3]=dp[下标1]+2等于4,dp[下标6]同理等于dp[下标4]+2等于2,当程序走到下标7时,下标6为")",又已知dp[6]等于2,因此我们需要向前滑动dp[6]的合法子串距离,即i-1-dp[6]的位置下标4的下标是否还存在且s[4]是否等于"(",如果等于“(",因为很有可能前面相连的字符串有括号闭合的情况,比如下面这种,需要把前面相连的已经闭合的括号的连续子串都相加,再去判断在i-1-dp[6]的前一个位置即i-2-dp[6]即下标3是否还存在,如果还存在则把dp[3]+dp[6]+2即dp[i-2-dp[i-1]]+dp[i-1]+2等于8,而下标8则是i-1-dp[7]即下标-1不存在dp[8]=0

0

2

0

4

0

0

2

8

0

0

1

2

3

4

5

6

7

8

代码如下:

public class Solution32 {
    

    public int longestValidParentheses(String s) {

        int dp[] = new int[s.length()];
        if (s.length() < 2)
            return 0;

        if (s.charAt(0)=='('&&s.charAt(1)==')'){
            dp[0] = 0;
            dp[1] = 2;
        }else{
            dp[0] = 0;
            dp[1] = 0;
        }

        for(int i = 2;i<s.length();i++){
            if (s.charAt(i)=='(')
                dp[i] = 0;
            else{
                if (s.charAt(i-1)=='(')
                    dp[i]= dp[i-2]+2;
                else{
                    if (i-1-dp[i-1]>=0&&s.charAt(i-1-dp[i-1])=='('){
                        if (i-2-dp[i-1]>0)
                            dp[i] = dp[i-2-dp[i-1]]+dp[i-1]+2;
                        else
                            dp[i] = dp[i-1]+2;
                    }
                }
            }
        }


        return max(dp);
    }

    private int max(int[] dp) {
        int max = 0;
        for (int i = 0;i<dp.length;i++){
            if (max<dp[i])
                max = dp[i];
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值