其他分享
首页 > 其他分享> > leetcode-32.最长有效括号

leetcode-32.最长有效括号

作者:互联网

题目:
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。 动态规划的详细思路和推倒过程写在注释了

class Solution {
public:
    int longestValidParentheses(string s) {
        int max = 0; 
        int N = s.size();
        if ( N < 2) {
            return 0;
        }
        // 为了理解动态规划的思路,我们按照 暴力求解 --> 动态规划的过程
        // 首先,我们知道,最终的最长有效括号,一定是以字符串s的某个位置为结尾,但是这个位置是不固定的
        //  1. 暴力求解
        //     很自然,我们就会想到,我们把以字符串s的每个位置为结尾的有效括号全部找出来,然后在所有的有效括号中找出最长 的就得到答案了
        //  2. 对暴力求解的分析
        //      如果分析暴力求解的所有结果,就会发现,对于某一个位置i而言,我们会把它所有有效括号都找出来,但是我们需要的是最长的那个,
        //      比如对于字符串"()()"的最后一个位置,我们可以找出两个有效括号由s[2]和s[3]构成的2个长度的(),以及由s[0]s[1]s[2]s[3]构成的4个长度的()(),而我们其实只需要由s[0]s[1]s[2]s[3]构成的,然后我们将以每个位置为结尾的最大有效括号长度做对比,取出最大的那个,就是答案
        //    因此从这个角度看,我们定义dp[N], dp[i]其含义为以字符i结尾的(必须包含i位置字符)的最大有效括号长度
        //    基于这个定义,我们最终要返回的是dp[N]中的最大值,而不是dp[N-1]
        //    很多同学没有理解这个dp数组含义,把以字符i结尾的最大有效括号长度,等同于了”到字符i为止的字符串所包含最大有效括号长度“,导致dp数组无法递归下去
        //    因为如果按照错误的理解,对于字符串 ”(())(“那么就会想返回dp[N-1],
        //    就会得到这样的dp数组, dp[0] = 0; dp[1]=0, dp[2]=2,dp[3]=4,dp[4]=4, 请注意dp[4], 按照错误的定义的话,dp[4]是应该等于4,因为它自己虽然不能构成新的有效括号,但是它前面的括号已经构成了4个长度的括号,到s[4]为止的字符串,至少是有4个长度的括号的,因此dp[4]=4,
        //    然而一旦误入这个解释,就会发现无法解决各种括号的匹配问题,怎么也递归不下去到dp[N-1]
        //    因此强调一下, dp[i]其含义为以字符i结尾的(必须包含i位置字符)的最大有效括号长度, 而不是”到字符i为止的字符串所包含最大有效括号长度“

        std::vector<int> dp (N, 0);
        for ( int i = 1; i < N ; i++ ) {
            if ( s[i] != ')' ) {
                continue;
            }
            int pre = i - dp[i-1] - 2; 
            // 说明当前位置的字符s[i]=')', 且s[i-1]='(’, 两者构成有效括号,其长度为dp[i-1]+2
            // 还应该考虑,一旦当前字符和其前一个字符构成有效括号后,它还可能和当前有效括号的前一个有效括号连起来,
            // 构成更长的有效括号
            if ( s[i-1] == '(' ) {
                dp[i] = dp[i-1] + 2;
                if ( pre >= 0) {
                    dp[i] = dp[i] + dp[pre];
                }
            }
            // 如果s[i]的前一个字符不是'(', 则需要判断 s[i] 是否可以和遥远的更左边(i - dp[i-1] -1)构成有效括号
            else {
                int index = i - dp[i-1] -1; 
                // index 越界, 比如())的最后一个字符
                if ( index < 0 ) {
                    dp[i] = 0;
                }
                else if ( s[index] == '(' ) {
                    dp[i] = dp[i-1] + 2; 
                    // 下面代码同之前是一样的含义解决 类似 (())(()) 的最后一个字符的括号长度计算情景
                    if ( pre >=0 ) {
                        dp[i] = dp[i] + dp[pre];
                    }
                }
                else {
                    // 这个代表找到遥远的括号,可惜对方和自己不是一对,无法构成有效口号,比如 )())的最后一个字符
                    dp[i] = 0;
                }  
            }
            max = std::max( max, dp[i] );
        }
        return max;
    }
};

  

标签:字符,括号,int,32,有效,长度,leetcode,dp
来源: https://www.cnblogs.com/houjianli/p/16412923.html