给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
【困难】
题意是找到最长的连续有效括号:如s="()(()",有效的连续括号只有(),答案应该是2.
一开始理解错了,以为是要求所有有效括号的总长度。。。。
【分析】利用栈。遍历s:
1 遇到"("时
,将左括号标压入栈内
2 遇到")"时
:
- 如果栈不空:弹出栈顶元素,并将右括号的下标同栈顶元素做差值得到括号的length。
- 如果栈为空:将右括号的下标压入栈内(相当于将后面的左括号的index-1记录下来,便于下一个连续括号的长度计算)
注1. 当s="(()))"
时,为了统一计算length
,设栈内初始元素为-1.
举个例子,做差值的思路其实相当于:
在栈弹出1之后,遇到了3,弹出0,栈顶元素为-1,此时length=3-(-1)
.差值相当于在[当前遍历的最右端的右括号]和[有效连续的最左端括号]之间建立了联系。
class Solution(object):
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
stack=[-1]
length_max=0
i=0
while i<len(s):
if s[i]=="(":
stack.append(i)
else:
stack.pop()
if stack:
length=i-stack[-1]
if length>length_max:
length_max=length
else:
stack.append(i)
i+=1
return length_max
【分析2】不需要额外空间。left
记录左括号的个数,right
记录右括号的个数
当left<right
,说明上一段有效括号的记录结束,可能有下一段有效括号要开始了。此时初始化left
和right
便于下一段有效括号长度的计算,left=0,right=0
。当left==right时
,说明这是一段有效括号,记录长度。
注:上述是从左往右遍历。但是,这道题,还需要从右往左按相同的原理再遍历一遍。因为s="(()" 时从左往右不能能正确记录长度,因为left
始终小于right
,此时需要从右往左遍历。
class Solution(object):
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
length_max=0
left,right=0,0
#左→右
for i in range(len(s)):
if s[i]=="(":
left+=1
else:
right+=1
if left==right:
length=2*left
if length>length_max:
length_max=length
elif left<right:
left,right=0,0
#右→左
left,right=0,0
for i in range(len(s)-1,-1,-1):
if s[i]==")":
right+=1
else:
left+=1
if left==right:
length=2*left
if length>length_max:
length_max=length
elif left>right:
left,right=0,0
return length_max
【分析3】dp