LeetCode 32 最长有效括号 题解

题目大意

给定一个由左右括号()组成的字符串,然后判断其中最长的有效括号子串长度(即左右括号可以匹配的子串)。

分析与源代码

一、时间复杂度为O(n^2)的DP算法

这道题我首先想到的是动态规划解法,设dp[i][j]为1表示s[i][j]为有效括号子串,那么会有两种情况的时候dp[i][j]为1:

第一种是dp[i+1][j-1]=1且s[i]='(',s[j]=')';

第二种是枚举k(k>=i,k<=j-1),在k处将其断开,分为s[i][k]与s[k+1][j],如果s[k]='('且s[k+1]=')'且dp[i][k]与dp[k+1][j]为1;

这样每次对dp[i][j]赋值为1的时候考虑一次最大值更新即可。

这种算法的思路比较简单,但是在leetcode评测时会超时几组数据,所以需要采用下面的方法。

public int longestValidParentheses(String s) {
        if(s == "") {
            return 0;
        }
        int len = s.length(), maxm = 0;
        boolean dp[][] = new boolean[len + 5][len + 5];
        for(int i = 0; i < len; i++) {
            dp[i][i] = false;
            if(i < len - 1) {
                if(s.charAt(i) == '(' && s.charAt(i + 1) == ')') {
                    dp[i][i + 1] = true;
                    maxm = 2;
                    continue;
                }
            }
        }
        for(int d = 2; d <= len - 1; d++) {
            for(int start = 0; start <= len - d - 1; start++) {
                int end = start + d;
                if(d % 2 == 0) {
                    dp[start][end] = false;
                    continue;
                }
                if(s.charAt(start) == '(' && s.charAt(end) == ')' && dp[start + 1][end - 1]) {
                    dp[start][end] = true;
                    maxm = Math.max(d + 1, maxm);
                }
                for(int i = start; i <= end - 1; i++) {
                    if(dp[start][i] && dp[i + 1][end] && s.charAt(i) == ')' && s.charAt(i + 1) == '(') {
                        dp[start][end] = true;
                        maxm = Math.max(d + 1, maxm);
                    }
                }
            }
        }
        return maxm;
    }

二、时间复杂度为O(n)的DP算法

我们设dp[i]表示以i结尾的最长合法括号子串的长度,那么如果s[i]=')'且s[i-1]='(',那么dp[i] = dp[i - 2] + 2,如果s[i-1]=')',那么这个时候就要去考虑s[i - dp[i - 1] - 1]的情况,如果为(,那么可以构成合法括号子串,接下来就需要考虑加上dp[i - dp[i-1]-2],因为这里会把这两个(以s[i]结尾与以s[i - dp[i - 1] - 2]结尾)子串组成一个合法括号子串。

public static int longestValidParentheses(String s) {
        if(s == "") {
            return 0;
        }
        int len = s.length(), maxm = 0;
        int dp[] = new int[len + 5];
        for(int i = 1; i < len; i++) {
            if(s.charAt(i) == ')') {
                if(s.charAt(i) == '(') {
                    dp[i] = dp[i - 2] + 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;
                }
                maxm = Math.max(maxm, dp[i]);
            }
        }
        return maxm;
    }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值