最长有效括号

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

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

思路一:动态规划

将dp数组初始化为全0。
当遇到某个字符为" ) "时,更新dp数组的值。

  1. 情况一:
    s[i - 1] == " ( ",即s[i] 和s[i - 1]组成一对有效括号,有效括号长度新增长度2,i位置对的最长有效括号长度为其之前2个位置的最长括号长度加上当前位置新增的2,我们无需知道i - 2位置对字符是否可以组成有效括号对。

  2. 情况二:
    s[ i - 1] == " ) "。这种情况下,如果前面有和s[i]组成有效括号对的字符,即形如((……)),这样的话,就要求s[i - 1]位置必然是有效括号对,否则s[i]无法和前面对字符组成有效括号对。

这时,我们只需要找到和s[i]配对对位置,并判断其是否是 ( 即可。由于i-1处的 ( 必然有一个 ) 与之对应,就两种情况,要么i-2处是 ( 与 i-1处的 ) 对应上,要么i-2处还是 ) ,要跟i-3处的 ( 对应上,然后还要保证i-4处的也是 (,当然,i-4处有可能不是了,那就不满足条件,这我后面会讲到。然后,我们假定已经知道dp[i-1]的大小,也就是前面已经有几个有效括号对了,比如 ( ) ( ( ) ) ,在求最后一个括号dp[i]的时候,dp[i-1]已经知道是2(形成一对有效括号+2,而不是+1)。此时为了找最后一个右括号的左括号,需要向前移动三个单位长度,因为这表明有内部括号,然后需要跳到内部括号的最前面去找。好了,这样的话i - dp[i-1] - 1就是与i处的右括号对应的左括号的位置了。
那么有:dp[i] = 2 + dp[ i - 1] + dp[ i - dp[i-1] -2 ]
其中第2项代表内部括号,第3项代表内部括号前面还有没有独立的有效括号组。可以看到,刚刚分析了这么多,分析出来了i - dp[i-1] - 1的目的就是为了找到 i - dp[i-1] -2 的!。
在这里插入图片描述


class Solution
{
public:
    int longestValidParentheses(string s)
    {
        int size = s.size();
        vector<int> dp(size, 0);

        int maxVal = 0;
        // 注意!!注意!!i = 1开始,因为后面有s[i-1],否则会字符串越界!!!!
        for (int i = 1; i < size; i++)
        {
            if (s[i] == ')')
            {
                if (s[i - 1] == '(')
                {
                    dp[i] = 2;
                    if (i - 2 >= 0)
                    {
                        dp[i] = dp[i] + dp[i - 2];
                    }
                }
                else if (dp[i - 1] > 0) // 有子有效括号组
                {
                    if ((i - dp[i - 1] - 1) >= 0 && s[i - dp[i - 1] - 1] == '(') // 防止越界并且找到了对应位置上的左括号
                    {
                        dp[i] = dp[i - 1] + 2;
                        if ((i - dp[i - 1] - 2) >= 0)
                        {
                            dp[i] = dp[i] + dp[i - dp[i - 1] - 2];
                        }
                    }
                }
            }
            maxVal = max(maxVal, dp[i]);
        }
        return maxVal;
    }
};

思路三:栈方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值