LeetCode 32. 最长有效括号

本文介绍了一种使用栈和排序解决最长有效括号子串问题的方法,通过遍历括号字符串并利用栈来记录匹配的索引,再对这些索引进行排序,最后找出最长的连续子序列。

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”

示例 2:

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

解题思路
栈+排序

括号匹配,第一时间想到用栈进行匹配,保存下可以匹配的索引下标。然后将匹配索引排序,找到最长连续子序列。

  1. 初试化栈stack = []和匹配索引数组res = []

  2. 遍历括号字符串:

    ∘\circ 若s[i] == “(”,若出现左括号,将其索引加入栈。
    ∘\circ 若stackstack不为空且s[i] == “)”,表示出现右括号,且栈里有左括号。

     将匹配的左括号的索引stack.pop()加入resres中
     将匹配的右括号索引i加入栈。
    
  3. 将resres排序。

  4. 初始化最长长度max_len=0,寻找res的最长连续子序列。循环条件,i<len(res)−1:

    ∘\circ令tmp=i保存最长连续子序列的左界
    ∘\circ 进入循环,循环条件i<len(res)-1且下一位和当前位差为1,res[i+1]−res[i]==1:

      令i=i+1i=i+1
    

    ∘\circ max_len=max(max_len,i-tmp+1)
    ∘\circ i+=1

  5. 返回max_len

复杂度分析

  • 时间复杂度:O(nlog(n)),括号匹配O(n),排序复杂度O(nlog(n)),寻找最长连续子序列O(n),总体O(nlog(n))
  • 空间复杂度:O(n)
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        res=[]
        stack=[]
        for i in range(len(s)):
            if(stack and s[i]==")"):
                res.append(stack.pop())
                res.append(i)
            if(s[i]=="("):
                stack.append(i)
        #print(res)
        res.sort()
        max_len=0
        i=0
        while(i<len(res)-1):
            tmp=i
            while(i<len(res)-1 and res[i+1]-res[i]==1):
                i+=1
            max_len=max(max_len,i-tmp+1)
            i+=1
        return max_len
栈(优化)
  1. 特判,若s为空,返回0

  2. 初始化栈stack=[-1],和结果res=0。栈中元素表示上一不匹配位置索引。

  3. 遍历s:

    ∘\circ 若s[i] == “(” 将当前位置索引加入stackstack。表示将当前左括号需要匹配,为不匹配索引。
    ∘\circ 若s[i]==")":

    • 出栈,stack.pop()。表示将对应左括号索引出栈,或者当栈中只有)时,将上一)索引出栈。
    • 若栈为空,表示之前的所有的(匹配成功,上一步出栈的是栈底的-1或者是前一个不匹配的)。则更新栈底为当前)的索引,表示不匹配的位置。
    • 否则,说明和栈中的(匹配上了,此时更新最长序列res=max(res,i-stack[-1])。表示当前位置索引减去上一不匹配位置索引 和之前res中的较大值。
  4. 更新res

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        if(not s):
            return 0
        stack=[-1]
        res=0
        for i in range(len(s)):
            if(s[i]=="("):
                stack.append(i)
            else:
                stack.pop()
                if(not stack):
                    stack.append(i)
                else:
                    res=max(res,i-stack[-1])
        return res

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值