最长有效括号 动态规划与非动态规划

32. 最长有效括号

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

示例 1

输入:s = "(()"

输出:2

解释:最长有效括号子串是 "()"

示例 2

输入:s = ")()())"

输出:4

解释:最长有效括号子串是 "()()"

示例 3

输入:s = ""

输出:0

思路:

    这个题有两个方法,我感觉都挺好用且好理解的。就都写一下吧~

    首先是动态规划的方法,但不是那么好想。如果想直接快乐解决,就直接看方法二吧。

方法一:动态规划

  定义一个动态规划数组dp[]dp[i]表示以i结尾的最长有效括号长度。这算是一个比较常见的定义方式了——“以i位置结尾”。

  状态转移方式:从左往右遍历字符串,如果遇到‘)’,就向前去寻找‘(’,寻找的过程中,要跳过dp[i-1]的长度。找到‘(’后,假设这个‘(’位置在pre,则dp[i]要再加上dp[pre-1]

  对于dp数组的初始化自然都是0

方法二:两次遍历,轻松解决

  这个方法是好记又好用!专门为了这个题而生,动态规划是理想!两次遍历是生活!

  第一次遍历,从左往右,分别记录下‘(’和‘)’的数量,当左括号数量大于右括号数量时,继续遍历;当左右括号数量相等时,如果当前长度大于最大长度,更新当前长度为最大;当左括号小于右括号时,当前遍历的字符串不合法,左右括号数清零。继续遍历;

  第二次遍历,从右往左,同样记录下‘(’和‘)’的数量,大致逻辑相同,但对应相反的是,当左括号数量大于右括号时,说明字符串不合法,左右括号数清零。继续遍历;

  通过这样两次遍历,最终得到的最大长度就是最终结果。因为我们要找到最长有效括号,其实很多情况下面临的问题就是不知道是从左开始匹配还是从右开始,通过这样两边都尝试一下,就可以遍历更新得到最终结果了。

代码1:(动态规划)

def longestValidParentheses( s):

    length = len(s)

    if length == 0:

        return 0

    dp = [0] * length

    #dp[i]表示以i结尾的最长有效括号长度

    for i in range(1,length):

            #当遇到右括号时,尝试向前匹配左括号

        if s[i] == ')':

            pre = i - dp[i-1] -1

            #如果是左括号,则更新匹配长度

            if pre>=0 and s[pre] == '(':

                dp[i] = dp[i-1] + 2 #直接加上这一对!数量+2



                #接下来处理独立的括号对的情形 类似()()、()(()) 中的第一对括号,需要额外去加

                #注意这个if是在上个if里面

                if pre!=0:#pre前面还可能有,只要pre不是第0位

                    dp[i] += dp[pre-1]#dp[i]要再加上dp[pre-1]

    return max(dp)

代码2:(向右遍历一遍,向左遍历一遍)

class Solution(object):

    def longestValidParentheses(self, s): 

        n, left, right, maxlength = len(s), 0, 0, 0

        for i in range(n):#第一次遍历 向右遍历

            if s[i] =='(':

                left+=1

            else:

                right+=1

            if left == right:#左右括号相等时,更新最大长度

                maxlength = max(maxlength, 2 * right)

            elif right > left:#右括号多于左括号,不合法,全部清零

                left = right = 0

        left = right = 0

        for i in range(n-1,-1,-1):#第二次遍历,向左遍历

            if s[i] =='(':

                left+=1

            else:

                right+=1

            if left == right:

                maxlength = max(maxlength, 2 * left)

            elif right < left: #若左括号多了,则不合法,清零继续

                left = right = 0

        return maxlength

小结:

    这道题动态规划方法不是特别容易想,但是一旦把这个方法呈现出来,就很好理解了,有妙到拍大腿的感觉~

    要准备面试的话我推荐记住方法2的套路,正反遍历一次,就可以得到最终结果啦。不过很显然,动态规划是普适性(可以解决其他很多题),后者是针对性的套路。

posted @   JunanP  阅读(10)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示