Given a string containing just the characters '('
and ')'
, find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"
LeetCode:链接
解题思路:返回括号串中最长合法括号串的长度。
第一种方法:使用栈。
(1)我们用一个栈去储存字符串的下标索引,用于后期的长度的推算。
(2)遇到 '(' 就进栈,遇到 ')' 就出栈,在出栈的时候要分情况谈论。
(3)当遇到 ')' 就出栈,如果此时,出栈后,栈已经为空,那么就把当前 i 值(位置索引)放入栈中,相当于入栈了一个')',为什么?它可以作为一个新子串的开始,用于后期合法子串的长度的计算。
(4)当遇到 ')' 就出栈,如果此时,出栈后,栈不为空,当前合法子串长度为:i - stack[-1],为什么是 i - stack[-1]?这个很好理解,stack[-1]是栈顶元素,即离当前合法子串左边最近的一个字符,i 是当前位置的索引,也就是 ')' 的位置,所以差就是合法子串的长度,随着不断进栈或者出栈,长度也会发生变化,我们保留最长的一个就可以了。
class Solution(object):
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
stack = [-1]
maxlen = 0
for i in range(len(s)):
if s[i] == '(':
stack.append(i)
else:
stack.pop()
# 如果栈为空,当前位置索引进栈,做为一个新的子串的开始
if not stack:
stack.append(i)
else:
# 更新合法子串的长度
maxlen = max(maxlen, i - stack[-1])
return maxlen
第二种方法:DP。和LeetCode5:Longest Palindromic Substring思路一样。
(1)设 dp[i] 表示以第i个字符结尾的最长合法字串的长度,初始化全为0。比如"()()()(()())"的dp结果就是02 04 06 0020412。
(2)对整个字符串进行一次遍历操作,遇到 '(' 时,不用操作,因为以 '(' 结尾的子串一定不是合法的。
(3)当遇到的字符是 ')' 时,要具体分析,因为以 ')' 结尾的串可能是合法的也可能是不合法的。
A、如果 s[i-1] == '(' 则,dp[i] = dp[i-2] + 2 ,因为前一个是非法结尾,可以形成一对合法的括号,所以直接加2。
B、如果 s[i-1] == ')' 则,在当前字串前,可能存在一个合法的子串,也可能不存在合法的子串。现在我们要找到 s[i - 1 - dp[i - 1]] 这个字符,判断它是否=='(',如果等于还可以是合法的。
a、在 s[i - 1 - dp[i - 1]] =='(' 的位置之前,如果也存在一个合法的子串,那么现在也应该把他添加到 dp[i] 中,所以 dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2。
b、否则就是直接在两端添加一对括号,所以总的长度增加 2,dp[i] = dp[i - 1] + 2。
需要注意的是,要判断向前查找的过程,数字不要越界。
class Solution(object):
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
dp = [0] * len(s)
res = 0
for i in range(len(s)):
if s[i] == ")": # 只考虑以')'结尾的子串
if i-1 >= 0 and s[i-1] == "(": # 第一种情况,直接加2
dp[i] = dp[i-2] + 2
elif i >= 1 and s[i-1] == ")":
# 第二种情况
if i-1-dp[i-1] >= 0 and s[i-1-dp[i-1]] == "(":
# 当前合法子串,前面还有子串的情况 "()()()(()())" 02 04 06 0020412
if i-1-dp[i-1]-1 >= 0:
dp[i] = dp[i-1] + dp[i-1-dp[i-1]-1] + 2
# 当前合法子串,前面没有子串的情况
else:
dp[i] = dp[i-1] + 2
res = max(res, dp[i])
return res