32. 最长有效括号!!(栈)

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

示例 1:

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

示例 2:

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

困难
题意是找到最长的连续有效括号:如s="()(()",有效的连续括号只有(),答案应该是2.

一开始理解错了,以为是要求所有有效括号的总长度。。。。

【分析】利用栈。遍历s:

1 遇到"("时,将左括号标压入栈内
2 遇到")"时

  • 如果栈不空:弹出栈顶元素,并将右括号的下标同栈顶元素做差值得到括号的length。
  • 如果栈为空:将右括号的下标压入栈内(相当于将后面的左括号的index-1记录下来,便于下一个连续括号的长度计算)

注1. 当s="(()))"时,为了统一计算length,设栈内初始元素为-1.

举个例子,做差值的思路其实相当于:
在这里插入图片描述
在栈弹出1之后,遇到了3,弹出0,栈顶元素为-1,此时length=3-(-1).差值相当于在[当前遍历的最右端的右括号]和[有效连续的最左端括号]之间建立了联系。

class Solution(object):
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        stack=[-1] 
        length_max=0
        i=0
        while i<len(s):
            if s[i]=="(":
                stack.append(i)
            else:
                stack.pop()
                if stack:
                    length=i-stack[-1]
                    if length>length_max:
                        length_max=length
                else:
                    stack.append(i)
            i+=1
        return length_max    

【分析2】不需要额外空间。left记录左括号的个数,right记录右括号的个数

  • 当left<right,说明上一段有效括号的记录结束,可能有下一段有效括号要开始了。此时初始化leftright便于下一段有效括号长度的计算,left=0,right=0
  • 当left==right时,说明这是一段有效括号,记录长度。

:上述是从左往右遍历。但是,这道题,还需要从右往左按相同的原理再遍历一遍。因为s="(()" 时从左往右不能能正确记录长度,因为left始终小于right,此时需要从右往左遍历。

        
class Solution(object):
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        length_max=0
        left,right=0,0
        #左→右
        for i in range(len(s)):
            if s[i]=="(":
                left+=1
            else:
                right+=1
            if left==right:
                length=2*left
                if length>length_max:
                    length_max=length
            elif left<right:
                left,right=0,0
        
        #右→左
        left,right=0,0
        for i in range(len(s)-1,-1,-1):
            if s[i]==")":
                right+=1
            else:
                left+=1
            if left==right:
                length=2*left
                if length>length_max:
                    length_max=length
            elif left>right:
                left,right=0,0
        return length_max

【分析3】dp

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值