Leetcode 032 最长有效括号 思路详解 + 反思总结 python

本人一直在努力地积累Leetcode上用Python实现的题,并且会尽力讲清每道题的原理,绝不像其他某些博客简略地带过。
如果觉得讲的清楚,欢迎关注。

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

示例 1:

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

示例 2:

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

思路一:栈

思路1:通过进栈出栈的方式保存一些括号的index。这个stack,右括号想进去,只有可能是上一个stack顶部元素也是右,而第一个右括号怎么进?只能在stack为空的时候进,而且进还必须得连续进,否则只有把最新的左括号pop出来才能进。

#以下为第一种思路,通过栈来判断当前位置对应的括号是否符合有效长度
class Solution:
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        j = len(s)
        maxlen = 0
        #stack用来保存的是一些括号(不一定全是左,也不一定全是右)在s中的index
        stack = []
        #遍历index
        for i in range(j):
            #如果遇到一个右括号并且我们的stack里有东西可以pop出来
            #并且那个即将pop出来的东西是左括号,我们就pop
            if s[i] == ')' and len(stack) != 0 and s[stack[-1]] == '(':
                a = stack.pop()
                #如果pop完刚好 stack长度为0,说明这种情况是那种完全对称形的并且刚好结束一次有效括号的排列
                #则我们需要计算此时的maxlen
                if len(stack) == 0:
                    maxlen = i + 1
                #如果还有剩下的括号,我们则更新此时的最长长度
                else:
                    maxlen = max(maxlen, i - stack[-1])

            else:
                stack.append(i)

        return maxlen



但是这种写法有点不明晰,来看看比较清楚的一种

思路:只在遇到左括号时放入栈中。这题是valid parentheses的扩展,也可以利用栈结构来实现。这里我们用栈存放左括号的下标,遇到左括号,将其下标存入栈中。遇到右括号,若此时栈为空,说明这个不是有效括号对里的,跳过,更新有效括号的起始点;若是栈不为空,则栈顶元素出栈。此时,若栈为空,后面不一定没有接合法的有效括号对,所以,计算当前和有效括号起始点的距离,并更新最大值,如:()();若不为空,用当前位置距离栈顶元素的距离和maxlen中的最大值更新maxlen,如:()(()()。参考了Grandyang的博客。



class Solution:
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        tl = len(s)
        stack = []
        st = 0
        maxlen = 0
        for i in range(tl):
            #如果是左括号,直接入stack
            if s[i] == '(':
                stack.append(i)
            #如果右括号
            else:
                #如果stack里没有元素匹对,说明有效括号已经结束,更新起始位置
                if len(stack) == 0:
                    st = i+1
                    continue
                #有元素匹对
                else:
                    a = stack.pop()
                    #pop出一个左括号匹对
                    #如果此时没了,不能保证不继续有效括号,所以根据当前的最长距离去更新maxlen
                    if len(stack) == 0:
                        maxlen = max(i - st+1, maxlen)
                    #如果此时还有 则计算与栈顶的索引相减来计算长度
                    else:
                        maxlen = max(i-stack[-1], maxlen)

        return maxlen



思路二:动态规划

这题还能使用动态规划的方式解:

dp[i]为到i处最长的有效括号,如果s[i]为左括号,则dp[i]为0,因为若字符串是以左括号结束,则不可能为有效的;若是为右括号,有两种情况:

一:其前者s[i-1]为左括号,所以dp[i]=dp[i-2]+2;

二、s[i-1]为右括号且s[i-dp[i-1]-1]为左括号,所以 dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2],其中i-dp[i-1]-1对应对应最长括号的起始点

LeetCode OJ代码如下:


 
 
class Solution :
def longestValidParentheses ( self , s ):
"""
:type s: str
:rtype: int
"""
a = len (s)
if a < 2 :
return 0
maxlen = 0
#dp[i]表示刚好在s[i]以前(包括s[i]在内)的最长括号长度
#如果s[i] = '(', dp[i] = 0
dp = [ 0 for _ in range (a)]
for i in range ( 1 , a):
#当前i的对称点的索引
pos = i - 1 - dp[i - 1 ]
if s[i] == ')' and s[i - 1 ] == '(' and i - 2 >= 0 :
#等于前前项的最长长度+2
dp[i] = dp[i - 2 ] + 2
elif s[i] == ')' and pos >= 0 and s[pos] == '(' :
#等于上个对称点+2
dp[i] = dp[i - 1 ] + 2
if pos - 1 >= 0 :
#如果对称点前还有长度,则加上那段长度
dp[i] += dp[i - dp[i - 1 ] - 2 ]
return max (dp)

猜你喜欢

转载自blog.csdn.net/weixin_41958153/article/details/80843652