题目分析:
这一题是让我们找最长的有效括号,这与LeetCode 20. Valid Parentheses有些相似,我们也可以试着用栈的思路解决。我们也可以想,如果它某一段是匹配的那么在两侧在加入左右括号,那么也是匹配的,这是动态规划的思路。所以我在这里提供两种解法(经过实验栈的方法比较快,且容易理解):
栈的思路代码说明:
- 栈的思路:如果是左括号那么就让它的下标进栈
- 如果是右括号,我们先考虑栈为空,那么肯定不能出栈,证明这是一个起始点,我们标记一下
- 如果是右括号,且栈为空,那么先出栈,出栈后栈为空,那么长度就是
当前位置 - 起始位置 + 1
,出栈后栈不为空,那么长度就是当前位置 - 栈顶元素
- 返回最大长度即可
栈的思路测试代码:
class Solution:
def longestValidParentheses(self, s):
res, start, stack = 0, 0, []
for i in range(len(s)):
#如果是左括号那么就让它的下标进栈
if s[i] == '(':
stack.append(i)
else:
#如果是右括号,我们先考虑栈为空,那么肯定不能出栈,证明这是一个起始点,我们标记一下
if stack == []:
start = i + 1
else:
#如果是右括号,且栈为空,那么先出栈,出栈后栈为空,那么长度就是`当前位置 - 起始位置 + 1`,出栈后栈不为空,那么长度就是`当前位置 - 栈顶元素`
stack.pop()
#返回最大长度即可
res = max(res, i - start + 1) if stack == [] else max(res, i - stack[-1])
return res
print(Solution().longestValidParentheses("(((()(()")) #提交时请删除该行
动态规划代码说明:
- dp[i]表示从s[i]到s[s.length - 1] 包含s[i] 的最长的有效匹配括号子串长度
- 在s中从后往前
- 若s[i] == ‘(’,则在s中从i开始到s.length - 1计算dp[i]的值
- 在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,其下标为j = i + 1 + dp[i + 1]
- 若j没有越界,并且s[j] == ‘)’,则s[i … j]为有效括号匹配,dp[i] =dp[i + 1] + 2,这种情况是加后面的和一对匹配的括号
- 若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1],这种情况是j+1是(的,要加上dp[j + 1]
动态规划测试代码:
class Solution:
def longestValidParentheses(self, s):
length = len(s)
max = 0
#dp[i]表示从s[i]到s[s.length - 1] 包含s[i] 的最长的有效匹配括号子串长度
dp = [0 for i in range(length)]
#在s中从后往前
i = length - 2
while i >= 0:
#若s[i] == '(',则在s中从i开始到s.length - 1计算dp[i]的值
if s[i] == '(':
#在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,其下标为j = i + 1 + dp[i + 1]
j = i + 1 + dp[i + 1]
#若j没有越界,并且s[j] == ‘)’,则s[i ... j]为有效括号匹配,dp[i] =dp[i + 1] + 2
if j < length and s[j] == ')':
dp[i] = dp[i + 1] + 2
#若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1]
if j + 1 < length:
dp[i] += dp[j + 1]
if dp[i] > max:
max = dp[i]
i -= 1
return max
print(Solution().longestValidParentheses(')()())')) #提交时请删除该行