最长有效括号【python版】

本文介绍了如何利用动态规划和栈解决LeetCode上的‘最长有效括号’问题。通过创建一个mask列表记录括号匹配状态,并转化为寻找连续0的最长子串,最终找到最长有效括号子串的长度。示例代码用Python实现,详细解释了每个步骤和逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先来看下题目:

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

示例 1:

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

示例 2:

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

示例 3:

输入:s = ""
输出:0

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-valid-parentheses
 


上面这道题很多人用动态规划来做【不过自己这里太笨了,没做出来】。参考了另一位大佬的做法,他是用了一个mask,用来记录括号是否匹配,将不匹配的地方全部置为1,最后就转化成了求这个mask中连续0【满足匹配】元素的长度。这里我用python进行了实现,先附完整代码:

class Solution:
    def longestValidParentheses(self, s: str) -> int:
        if s == "":
            return 0
        stack = []
        mask = [0 for _ in range(len(s))]
        left,Len, ans =0,0,0
        for i in range(len(s)):
            if s[i] == '(': # 如果是左括号就加入栈
                   stack.append(i)
            else:
                if stack == []:# 如果栈为空
                    mask[i] = 1
                else: # 如果栈不为空,且为右括号,例如[(()] stack = [0,1,2]
                    stack.pop() # 右括号出栈[((] stack =[0,1]
        while stack != []:
            mask[stack[-1]] = 1 # 另无效的左括号为1
            stack.pop() # stack = [0]  [(]
        for i in range(len(s)):
            if mask[i]:
                Len = 0
                continue
            Len += 1
            ans = max(ans,Len)
        return ans


步骤:

1.如果s="",也就是输入为空,直接返回0

2.创造一个与字符串s长度一样的mask列表,并初始化为0,同时stack为栈,用来存储括号

3.for遍历s,然后有两个情况需要判断一下,第一种就是s的第一个元素是左括号"(",第二种就是第一个元素为右括号”)“。

第一种,如果遇到左括号"(",入栈stack.append(i)【这里放入的是下角标】。

如果第一个元素不是左括号【也就是第一个元素是右括号】,那么刚开始的stack没有左括号入栈,也就是刚开始是空,则mask对应的第一个角标位置为1,表示无效的匹配。

如果stack不为空【表示第一次for循环有”(“入栈】且是右括号,匹配成功,那么就执行stack.pop(),将这个右括号")"弹出。【弹出就只剩下左括号继续和后面的匹配】

4.通过上面的for循环匹配过滤多余或者说无效的右括号,还遗留了一个问题,那就是可能会有多余的左括号,因此需要将多余的左括号标记出来,所以我们可以用stack[-1]获得栈最上面的左括号的角标【C++中就是stack.top()】,每标记一次的同时,并将这个多余的也就是栈最上面的左括号弹出。在mask中标记出来并令其为1;【也就是代码中的mask[stack[-1]]】,直到stack为空的时候结束循环,这样我们就得到一个完整mask模板,它清楚的记录了记录了有效括号的下角标。

5.获得mask中连续0最长的长度即可

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱吃肉的鹏

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

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

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

打赏作者

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

抵扣说明:

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

余额充值