leetcode32. 最长有效括号-动态规划

leetcode32. 最长有效括号


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

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

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

动态规划

dp[i]表示以第i个字符开头的括号,拥有的字符串长度,根据当前是左括号还是右括号,有不同的操作。注释在代码里。


class Solution {
    public int longestValidParentheses(String s) {
        if (s.length() == 0) return 0;
        int[] dp = new int[s.length()];
        int max = 0;
        dp[s.length() - 1] = 0;
        for (int i = s.length() - 2; i >= 0; i--) {//从后往前遍历的
            if (s.charAt(i) == ')') {
            //当前是右括号,如果他的右边是左括号,需要把左括号的状态传递过来
            //比如(()()())(),最后dp应该是10,6,4,4,2,2,0,2,2,0。
            //如果没有传递状态,最后是0,2,0,2,0,2,0,0,2,0
            //这样会导致求出来的括号不是连续的,第一版代码就是这个问题,但是找不到代码了
                if (s.charAt(i + 1) == '(') {
                    dp[i] = dp[i + 1];
                } else {
                    dp[i] = 0;
                }
            } else {
            //当前是左括号
                if (s.charAt(i + 1) == ')') {
                //如果右边是右括号,那么应该和下一个配对,并且把右括号的状态加上
                    dp[i] = 2 + dp[i + 1];
                } else {
                //右边是左括号,那么可能是嵌套的情况
                    if (dp[i + 1] == 0) {
                    //为0说明右边没有连续的括号
                        dp[i] = 0;
                    } else {
                    //计算和他对应的位置是否是右括号
                        int r = i + dp[i + 1] + 1;
                        if (r < s.length() && s.charAt(r) == ')') {
                            dp[i] = 2 + dp[i + 1] + dp[r];
                            //当前括号的长度2+右边连续的括号长度+和当前括号匹配的右括号的状态
                        } else {
                            dp[i] = 0;
                        }
                    }
                }
            }
            max = Math.max(max,dp[i]);
        }
        //show(dp);
        return max;
    }
    public void show(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

leetcode 116

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值