leetcode热题100.最长有效括号(动态规划完结篇)

今天给大家带来一道leetcode经典题,最长有效括号,本文将介绍动态规划解法解法,希望对你有所帮助。这是动态规划系列的最后一题了,想要看之前动态规划的题解的小伙伴可以去热题100专栏获取🍗🍖🥩

题目

32. 最长有效括号 - 力扣(LeetCode)

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

子串的长度。

示例 1:

输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"

示例 2:

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

示例 3:

输入:s = ""
输出:0

提示:

  • 0 <= s.length <= 3 * 10^4
  • s[i] 为 '(' 或 ')'

思路

要找到字符串中最长的有效括号子串,我们可以使用动态规划的方法。我们定义一个数组dp,dp[i]的含义是字符串的第i位上最长的最长有效括号子串的长度。

我们从前往后遍历字符串求解 dp 值,我们每两个字符检查一次:

  • 如果s[i]=‘)’ 且 s[i−1]=‘(’,也就是字符串形如 “……()”,我们可以推出:

dp[i]=dp[i−2]+2

我们可以进行这样的转移,是因为结束部分的 "()" 是一个有效子字符串,并且将之前有效子字符串的长度增加了 2 。

  • 如果s[i]=‘)’ 且 s[i−1]=‘)’,也就是字符串形如 “……))”,我们可以推出:

                                如果 s[i−dp[i−1]−1]=‘(’,那么,

dp[i]=dp[i−1]+dp[i−dp[i−1]−2]+2

此时 s[i−dp[i−1]−1]和s[i]构成一堆字符串 “()”,所以我们+2

我们还需要加上s[i−dp[i−1]−1]之前一个位置的构成括号的数目,即dp[i−dp[i−1]−2]

在 i-dp[i-1]-1 和 i-1之间还有一段字符串,这段字符串所组成的符合要求的字符串长度就是dp[i-1]

通过上面的转移思想从后往前递推,就能得到我们想要的答案

方法

  1. 初始化一个长度为字符串长度的 dp 数组,初始值全为 0。

  2. 从第二个字符开始遍历字符串,对于每个字符:

    • 如果字符是右括号 )
      • 检查它的前一个字符是否是左括号 (。如果是,则它们可以组成一对有效的括号子串,更新 dp[i] = dp[i-2] + 2(如果 i-2 小于 0,则 dp[i-2] 为 0)。
      • 如果前一个字符也是右括号 ),则需要检查 i - dp[i - 1] - 1 位置上的字符是否是左括号 (,如果是,则可以将当前有效括号子串的长度加上,更新 dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2(如果 i - dp[i - 1] - 2 小于 0,则 dp[i - dp[i - 1] - 2] 为 0)。
  3. 最后返回 dp 数组中的最大值,即为最长有效括号子串的长度。

代码

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        if not s:
            return 0
        
        n = len(s)
        dp = [0] * n
        
        for i in range(1, n):
            if s[i] == ')':
                if s[i - 1] == '(':
                    dp[i] = dp[i - 2] + 2 if i >= 2 else 2
                elif i - dp[i - 1] > 0 and s[i - dp[i - 1] - 1] == '(':
                    dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2 if i - dp[i - 1] >= 2 else dp[i - 1] + 2
        
        return max(dp)

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓宜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值