给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def longestValidParentheses(self, s: str) -> int:
def test(temp1):
left2=0
right2=0
for j in temp1:
if j=='(':
left2+=1
else:
right2+=1
if left2<right2:
return False
return True
n=len(s)
if n==0:
return 0
left=0
right=0
temp=[]
max_len=0
for i in range(n):
if s[i]=='(':
left+=1
temp.append(s[i])
else:
right+=1
temp.append(s[i])
if left<right:
temp=[]
left=0
right=0
continue
left1=left
right1=right
temp1=temp[:]
while (temp1 and left1!=right1) or ((not test(temp1))and (temp1)):
if temp1.pop(0)=="(":
left1-=1
else:
right1-=1
if left1==right1 and len(temp1)>max_len :
max_len=len(temp1)
return max_len
这道题一开始我的思路,是先遍历一遍比如遍历到i时我们就来寻找以s[i]为结尾的有效括号子串的长度。
刚开始我寻找的思路是对以s[i]结尾的子串进行两道排查
1.首先在前面我统计了“(”和“)”的个数,分别为left和right,然后我们在该字串不停的踢出串首字符,同时记录left和right
2.当他们相等时我们需要进行第二道判断,即从头读取一遍该删减过的字符串看看是否会出现left<right的情况假如出现了则说明该子串包含不有效子串“)(”,我们需要把它放到循环里继续从串首踢出元素。
class Solution:
def longestValidParentheses(self, s: str) -> int:
n=len(s)
dp=[0]*n
max_len=0
for i in range(n):
if s[i]=='(':
dp[i]==0
elif i-dp[i-1]-1==0and s[0]=='(':
dp[i]=dp[i-1]+2
elif i-dp[i-1]-1>0and s[i-dp[i-1]-1]=='(':
dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]
if dp[i]>max_len:
max_len=dp[i]
return max_len
由于上一种方法的时间复杂度不符合要求,我们俩用时间换空间,我的想法是当我们遍历到i时我们要判断以s[i]为串尾的有效字串的长度时,我们可以利用之前保存的j<i以是s[j]结尾的字符串的的有效子字符串的长度来判断以s[i]结尾的字符串的有效子字符串的长度。
假如s[i]"("那么肯定不存在以s[i]结尾的有效子字符串
如果是s[i]")"
我们发现公式dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]
而当 i-dp[i-1]-1==0时由于dp[i-dp[i-1]-2]不存在所以单独考虑,但由于dp[-1]等于零后来我又把他们这两种情况结合到了一起
即
class Solution:
def longestValidParentheses(self, s: str) -> int:
n=len(s)
dp=[0]*n
max_len=0
for i in range(n):
if s[i]==')':
# if i>0and s[i-1]=='(':
# dp[i]=dp[i-2]+2
if i-dp[i-1]-1>=0and s[i-dp[i-1]-1]=='(':
dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]
if dp[i]>max_len:
max_len=dp[i]
return max_len
class Solution:
def longestValidParentheses(self, s: str) -> int:
n=len(s)
dp=[0]*n
max_len=0
for i in range(n):
if s[i]==')':
if i>0and s[i-1]=='(':
dp[i]=dp[i-2]+2
elif i-dp[i-1]-1>=0and s[i-dp[i-1]-1]=='(':
dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]
if dp[i]>max_len:
max_len=dp[i]
return max_len
还有一种思路是,建立一个栈然后进行遍历,假如s[i]"(",则在栈中记录一个点位等待“)”与其配对
如果s[i]")“那麽我们需要从栈中将与s[i]最近的记录的点删除,表示这之间是有效括号子串,并且记录该长度。
由于假如s[i]")"我们就需要从栈中踢出一个与其对应的点,而当栈中没有与其对应的点的时候即stack为空的时候我们就无法踢出元素了或者假如前面所有的“(”都被消耗完了,这时候我们找不到一个标准来计算出i与最近删除的点之间的长度,wile解决这个问题我们设置一个初始的量度-1
还有当我们stack中只剩下-1而且是s[i]”)"那么我们需要将-1踢出并且使i成为新的那个量度因为不存在以“)”开头的有效括号。