• leetcode32.最长有效括号


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

    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;
        }
    };
    

      

  • 相关阅读:
    Data Wrangling文摘:Non-tidy-data
    Data Wrangling文摘:Tideness
    Python文摘:Mixin 2
    Python文摘:Mixin
    Python文摘:Python with Context Managers
    Python学习笔记11
    SQL学习笔记9
    SQL学习笔记8
    SQL学习笔记7
    Python学习笔记10:内建结构
  • 原文地址:https://www.cnblogs.com/houjianli/p/16412923.html
Copyright © 2020-2023  润新知