1.题目
原题:
给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
例子:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
2.解析
这道题可以好好盘一盘我的心路历程,里边全是坑,大家注意避着点。
先来说正确解法:栈和动态规划。
栈是这次考虑的重点,动态规划以后有空再补充。
2.1 我的错误做法
当时我思考的栈解决问题,但是我考虑的太复杂了,甚至加了双指针。
- 疑点1,为啥不用双指针
答:栈本来就是动态的,可以不断地入栈、出栈,本来就可以记录下标位置。 - 疑点2,用for循环还是while循环
答:其实都可以,for循环和while循环一层就可以了,不用考虑正确匹配的开始位置可能是第一个也能是第n个,因为栈可以记录下所有符合条件的括号集合。 - 疑点3,什么时候进行有效括号的计算
答:遇到左括号就入栈,这个是肯定的,因为只要是左括号,就可能有有效匹配,因此计算只能出在右括号里。
右括号也分情况: - 第一种是栈空了,注意这个栈空了的意思是没有左括号可以和这个右括号匹配,这个时候观察一下,i - start和当前最大有效括号lk(下面简称lk了)之间的最大值就是此次的lk。
这里的小疑点,为啥是i- start?因为有效的匹配位置是i-1,思考一下这个)括号不是有效的匹配,有效的匹配只到前一个位置,计算从开始位置到有效位置有多少位,i - 1 - start + 1(1到7有几个数?7-1+1 =7对不对),就是i-start。这个完事之后咱从下一位开始匹配,更新一下start。 - 第二种是栈没空,到此位置还是有效的,然后我们需要pop掉一个元素。pop完了又出问题了,栈空了,栈没空。(杨宗纬《我变了,我没变》)
假设栈空了,你能咋办,匹配完了呗,算一下几个括号,i - start + 1,这个不想解释了,参考上面的说法吧。
假设栈没空,哎没匹配完,有效的有几个啊,注意哦当前i位置是有效的,然后前面pop掉一个i - (stack[-1] + 1) +1 ,嗯算完了i - stack[-1]。stack是啥,你们觉得是啥,当然是左括号对应的下标啊。
2.2 正确做法
做出这道题总共分三步:
第一步,整个循环,遍历输入字符串。
第二步,设置一个start,随时更新着,设置一个stack,记录下左括号的下标。
第三步,开始操作,按照上一节的疑点3操作,对着代码看,可能更清楚一点。
3.python代码
class Solution:
def longestValidParentheses(self, s):
nlen = len(s)
i = 0
new_stack = []
lk = 0
start = 0
if nlen <= 1:
return 0
while i < nlen:
# print(i)
# print(new_stack)
# print('start', start)
if s[i] == '(':
new_stack.append(i)
else:
if new_stack:
new_stack.pop()
if new_stack == []:
lk = max(lk, i - start + 1)
else:
# print(2)
lk = max(lk, i - new_stack[-1])
else:
lk = max(lk, i - start)
start = i + 1
i += 1
return lk