题目:
给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())
" 输出: 4 解释: 最长有效括号子串为"()()"
思想:
看到括号匹配问题,首先想到了栈,这道题也确实要用栈.
第一种异常情况,右括号多出来:看示例我们发现右括号会多出来,这种情况是非常容易解决的,就是以右括号为边界,将右括号之间符合匹配规则的sum出来,然后取最大值。
第二种异常情况,左括号多出来:还有另一种情况,就是左括号多的时候,这里由于本人愚笨,花了很多时间,左括号之所以麻烦是因为当你遍历到‘)’时,只要没有‘(‘’则可以判断结束了,而遍历到‘(’就无法这么判断了,因为后面可能有')',举几个比较恶心的例子:
“(((())()(()(()))))))))))”
"((()((((()(((((()()()()()((((()))))(()))))"
这里因为就算知道了'('的数量,你也无法判断到哪里是异常发生点。
废话了一些,下面进入正题,首先我们要找到异常发生点,就是不是有效括号子串了,可能有无数个异常发生点,我们只要求出异常发生点之间的有效括号子串长度就可以了,然后取出最大的值。
接下来介绍异常点怎么找,如何找到异常点呢,这里很难通过"("的数量或者位置来查找,关键的一步来了,既然我们要把'('压入栈中,那我们就通过这个栈来找到了,那些多余出来的'('就是我们的异常点,那这里就有个问题,知道了异常点,怎么求异常点之间的子串长度,这里我们就要脑筋急转弯了,将子串长度压入这个栈不就可以了,栈结构就会像这样【异常点,子串长度,异常点,子串长度】。当然这里的子串长度不能一下子求出最长子串长度,但是我们可以匹配一个括号就压入一个长度。
代码:
这里用的是python写的,C++或者java可以将数字转为字符串,压入栈中。
class Solution:
def longestValidParentheses(self, s):
"""
:type s: str
:rtype: int
"""
if len(s) == 0:
return 0
lefts = []#栈
self.validlen = 0#当前匹配的长度
maxlen =0 #最大子串长度
for index, ch in enumerate(s):
#pring(lefts) #可以看每一次遍历,栈结构的变化
if ch == '(':
if self.findLeftCnt(lefts):#这一步是防止有多个(,无法计算最长子串
lefts.append(self.validlen)#如果左边有多余的左括号,则添加当前validlen
self.validlen = 0 #重置当前匹配长度
lefts.append('(') #压栈
elif ch == ')':
if '(' in lefts:#有左括号,则添加长度
self.validlen += 2
lefts.pop(self.findlastLeft(lefts))#弹出最近的一个(
if '(' not in lefts:
lefts.append(self.validlen)#先保存当前所得到的长度
self.validlen = 0
else:
if index == len(s) - 1:
lefts.append(self.validlen) # 先保存当前所得到的长度
self.validlen = 0
else:#没有匹配的左括号
lefts.append(')')
# print(lefts) #如果看不懂思路,请打印最后的栈结构
#下面就是找到最大的子串
templen = 0#保存异常点之间的子串长度
for ch in lefts:
if isinstance(ch, str):#发现一个异常点,则重新计算下一个异常点之间的子串长度
if templen > maxlen:#如果不是最大的子串
maxlen = templen
templen = 0
else:
templen += ch
if templen > maxlen:#因为栈末尾不一定有异常点,所以要加一步
maxlen = templen
return maxlen
def findlastLeft(self,lefts):
"""
找到最靠近栈顶的'('位置
:type lefts: 栈
:rtype: 最靠近栈顶的'('位置
"""
index = len(lefts)-1
while index >=0:
if lefts[index] == '(':
return index
index -= 1
return index
def findLeftCnt(selfs,lefts):
"""
这里不能通过数量判断,否则会超时
判断栈中是否有(
:param lefts: 栈
:return: 判断'('是否大于0
"""
cnt = 0
for ch in lefts:
if ch == '(':
return True
return False
if __name__ =="__main__":
res = Solution()
#'(()()(((((((())))))))'
print(res.longestValidParentheses(")()())()()("))
pass
结果:
我的代码不仅可以返回长度,还可以返回最长子串内容,只需要将异常点换位index就可以。.