难度:困难
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
思路:这种题采取动态规划的思想来做,首先我自己并没有想出来...也不算没想出来的吧,想出来了一半,然后去网上看一下别人的思路后大概就明白了。具体如下:
状态:dp[i] 表示以下标 i 为字符结尾的最长有效字符串的长度
状态转移方程:以 ( 结尾的子字符串不考虑,因为不可能构成合法括号
当 s[i] == ')'时,分为两种情况(我只想到了第一种情况)
1、s[i - 1] == '(',也就是字符串形如 “……()”,我们可以推出:dp[i] = dp[i − 2] + 2。因为结束部分的 "()" 是一个有效子字符串,前面的也是有效字符,所以很容易看出来是dp[i − 2] + 2.
2、s[i - 1] == ')',也就是字符串形如 “.......))”,我们可以推出:if s[i - dp[i - 1] - 1] == '(',dp[i] = dp[i − 1] + dp[i − dp[i − 1] − 2] + 2。因为如果倒数第二个 )是一个有效子字符串的一部分(记为subs),我们此时需要判断 subs 前面一个符号是不是 ( ,如果恰好是(,我们就用 subs 的长度(dp[i - 1)加上 2 去更新 dp[i]。除此以外,我们也会把子字符串 subs 前面的有效字符串的长度加上,也就是 dp[i − dp[i − 1] − 2].
边界情况:
1、i - 2 有可能小于零越界了,这种情况下就是只有 () ,前面记为 0 就好了.
2、i - dp[i - 1] - 1 和 i - dp[i - 1] - 2 都可能越界,越界了当成 0 来计算就可以了.
(以上第二种情况也是我没想到的,也是比较难想的,以上内容来源于Leetcode题解WoCa大佬写的)
遇见的坑:空串...
代码如下:
class Solution(object):
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
#判断空串
if len(s)<2:
return 0
dp = [0] * len(s)
for i in range(1, len(s)):
if s[i] == ')':
if s[i-1] == '(':
if i-2>0:
dp[i] = dp[i-2] + 2
else:
dp[i]=2
else:
j = i - dp[i-1] - 1
if j >= 0 and s[j] == '(':
dp[i] = dp[i-1] + 2
if j - 1 >= 0: dp[i] += dp[j - 1]
max1=max(dp)
return max1