【LeetCode热题100】32. 最长有效括号(动态规划)

一.题目要求

给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

二.题目难度

困难

三.输入样例

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

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

示例 3:
输入:s = “”
输出:0

提示:

  • 0 <= s.length <= 3 * 104
  • s[i] 为 ‘(’ 或 ‘)’

四.解题思路

  1. 有效括号分两种情况:
    • ( ) ( ) ()() ()() ,长度为 4 4 4
    • ( ( ) ) (()) (()) ,长度为 4 4 4 ,也是有效的
  2. 状态转移 d p [ i ] dp[i] dp[i] 表示 i i i 位置作为字符串结尾的情况下,字符串开头向左延伸出连续有效的子串长度
  3. 考虑上述两种情况后,状态转移的递推如下:
    • i i i 位置为左括号 ( ( ( , 则 d p [ i ] dp[i] dp[i] 一定是 0 0 0 ,因为有效子串必须以右括号 ) ) ) 结束。

    • i i i 位置为右括号 ) ) ) , 此时需要按照 1. 中两种有效括号的形式进行分类讨论:

      1. i − 1 i - 1 i1 位置是 左括号 ( ( (,此时 d p [ i ] dp[i] dp[i] 的值为 2   +   d p [ i − 2 ] 2\,+\,dp[i-2] 2+dp[i2] ,若 i − 1 i-1 i1 小于 0 0 0,则为 2 2 2
      2. i − 1 i - 1 i1 位置是 右括号 ) ) ),此时 d p [ i ] dp[i] dp[i] 的值为公式
        d p [ i ] = { 0 i − 1 − d p [ i − 1 ] < 0   或   s [   i − 1 − d p [ i − 1 ] ] = ′ ) ′ d p [ i − 1 ] + 2 ( i − d p [ i − 1 ] − 2 ) < 0   到左边界了 d p [ i − 1 ] + 2 + d p [ i − d p [ i − 1 ] − 2 ] ( i − d p [ i − 1 ] − 2 ) ≥ 0   相当于接上了之前的串 dp[i] =\begin{cases} 0 & i - 1 - dp [i-1] <0 \,或\,s[ \,i - 1 - dp [i-1]] = ')' \\\\dp[i - 1] + 2 & (i - dp [i - 1] - 2) < 0 \,到左边界了 \\ \\dp[i - 1] + 2 +dp[i - dp [i - 1] - 2] & (i - dp [i - 1] - 2) \geq 0 \,相当于接上了之前的串 \end{cases} dp[i]= 0dp[i1]+2dp[i1]+2+dp[idp[i1]2]i1dp[i1]<0s[i1dp[i1]]=)(idp[i1]2)<0到左边界了(idp[i1]2)0相当于接上了之前的串

      对应三种情况:
      在这里插入图片描述

五.代码实现

class Solution {
public:
    int longestValidParentheses(string s) {

        vector<int> dp(s.size(), 0);
        int len = 0;
        //dp[i] : 子串必须以i位置的字符结尾的情况下,往左最多推多远能整体有效
        for(int i = 1; i < s.size(); i++)
        {
            if(s[i] == ')')
            {
                if(s[i - 1] == '(')
                {
                    dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
                }
                else if(s[i - 1] == ')')
                {
                    if(i - 1 - dp [i - 1] >= 0 && s[i - 1 - dp [i - 1]] == '(')
                        dp[i] = dp[i - 1] + 2 + ((i - dp [i - 1] - 2) >= 0 ? dp[i - dp [i - 1] - 2] : 0);
                    
                }
            }
            len = max(dp[i] , len);
        }
        //for(auto v:dp) cout<<v<<endl;
        return len;
    }
};

六.题目总结

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值