题目描述
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
题解(动态规划)
第一思路是采用动态规划。假设已经有若干长度的有效括号,我们考察括号长度继续增长的两种形式:
- xxxx()
- (xxxx)
即增加独立的有效括号,或者在外部嵌套一层括号。我们令dp[i]代表以s[i]结尾的最长连续有效括号长度,初始化为0。如果s[i]为左括号,dp[i]=0。如果s[i]为右括号,我们分别讨论上述两种情况:
对于第一种情况,s[i-1]与s[i]分别为左括号与右括号,则有dp[i]=dp[i-2]+2。
对于第二种情况,也就是:①(②)。我们注意到,dp[i-1]表示了内部的有效括号的长度,那么与s[i]匹配的左括号应该是s[i-1-dp[i-1]]。如果二者匹配,则有dp[i] = dp[i-2-dp[i-1]] + dp[i-1] + 2,其中dp[i-2-dp[i-1]]是①的长度,dp[i-1]是②的长度,2是新加的两个括号。
代码(动态规划)
class Solution(object):
def longestValidParentheses(self, s):
n = len(s)
dp = [0 for i in range(n)]
rs = 0
for i in range(1, n):
if s[i] == ')':
if s[i-1] == '(':
dp[i] = dp[i-2] + 2 if i-2 >= 0 else 2
elif s[i-1] == ')' and i-1-dp[i-1] >= 0 and s[i-1-dp[i-1]] == '(':
dp[i] = dp[i-2-dp[i-1]] + dp[i-1] + 2 if i-2-dp[i-1] >= 0 else dp[i-1] + 2
rs = max(rs, dp[i])
print(dp)
return rs
题解(栈)
最为关键的思路是,栈中存储的并不是左右括号字符,而是未匹配的括号的位置。我一开始没有想明白这一点,因此耽误了比较久时间。
我们自左向右遍历字符串中的每一个字符,去检查它能否与栈顶代表的未匹配位置相匹配:
- 当且仅当栈顶元素所指的字符为左括号、当前字符为右括号时,二者匹配,出栈。新的栈顶所指示的位置与当前位置的差即为有效匹配的长度。我们取遍历过程中的所有长度的最大值,即为最终的最长有效匹配长度。
- 其他情况下,都不匹配,当前位置入栈。
代码(栈)
class Solution(object):
def longestValidParentheses(self, s):
stack = []
rs = 0
for i, ch in enumerate(s):
if stack and ch == ')' and s[stack[-1]] == '(':
stack.pop()
rs = max(rs, i - stack[-1] if stack else i + 1)
else:
stack.append(i)
return rs