32.最长有效括号(Longest Valid Parentheses)

题目描述:

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

示例 1:

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

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

解题思路:

  这个题我一开始也想到用动态规划去解决,不过状态转移方程没有找对,试了几种都是错的。最后无奈看了题解,发现题解的思路真的很巧妙。所以偶尔看一看别人的思路,学习别人优秀的想法,真的可以收获很多。

  dp的思路是:1)dp[i]表示,下标i为结尾的序列中,最长有效括号子串的长度。2)如果s[i]是‘(’,那么显然无法构成一个有效的序列,所以dp[i]为0,如果s[i]是‘)’,那么就需要联系前一个字符,来进行状态转换。3)如果s[i-1]是‘(’,那么s[i-1]和s[i]构成一对,所以这时只需要用dp[i-2]加上2即可。如果s[i-1]是‘)’,那么就需要判断以s[i-1]为结尾的有效子串的前一个字符是不是‘(’,如果是的话,dp[i]的值就等于dp[i-1]加上2再加上dp[i - dp[i-1] - 2]。

  最后一种情况相对难以理解,再解释一下就是:把s[i-1]为结尾的有效子串看成一个整体,这个整体的前一个字符如果是‘(’,就刚好可以和s[i]的‘)’组成一对,所以长度就变成s[i-1]结尾的子串长度加二。但是这样是不够的,如果现在这个加2以后子串前面正好还有有效子串,那么这两个子串就可以组成一个更长的有效子串,这就是最后加上dp[i - dp[i-1] - 2]的原因。

  代码如下:

class Solution {
public:
    int longestValidParentheses(string s) {
        // 保存下标i为结尾的序列中,最长有效括号子串的长度
        vector<int> dp(s.size());
        int ret = 0;
        for (int i = 1; i < s.size(); ++i) {
            if (s[i] == '(') {
                dp[i] = 0;
            } else if (s[i - 1] == '(') {
                if (i == 1)
                    dp[i] = 2;
                else
                    dp[i] = dp[i - 2] + 2;
            } else { // case : (s[i - 1] == ')')
                if (i - dp[i-1] - 1 >= 0 && s[i - dp[i-1] - 1] == '(')
                    if (i - dp[i-1] - 2 < 0)
                        dp[i] = dp[i-1] + 2;
                    else
                        dp[i] = dp[i-1] + 2 + dp[i - dp[i-1] - 2];
            }
            ret = max(ret, dp[i]);
        }
        return ret;
    }
};

 

posted @ 2020-05-10 20:26  简讯  阅读(165)  评论(0编辑  收藏  举报