给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”
没看清题目就写,以为是求输入中有效括号数。。。
A={'(':1,')':2}
zhan=[]
ans=0
if len(s)<=1:
return 0
for i in s:
zhan.append(i)
if len(zhan)>=2:
if A[zhan[-1]]==2 and A[zhan[-2]]==1:
zhan.pop()
zhan.pop()
ans=ans+2
return ans
那么就以它为函数来判断把,然而解答错误
if len(s)<=1:
return 0
def yxkh(s):
A={'(':1,')':2}
zhan=[]
ans=0
for i in s:
zhan.append(i)
if len(zhan)>=2:
if A[zhan[-1]]==2 and A[zhan[-2]]==1:
zhan.pop()
zhan.pop()
ans=ans+2
if zhan==[]:
return ans
else:
return 0
#上面是定义函数
A={'(':1,')':2}#其实可以不这么写,下面判断直接写== or !='(' ')'
ans=[]
start=0
end=start+1
while end <len(s):
if A[s[start]] !=1:
start=start+1
end=start+1 #这里错了,万一超出长度了
continue
if A[s[end]] !=2:
end=end+1
continue
ans.append(yxkh(s[start:end+1])) #计算开头和结尾分别为( )的片段
end=end+1
if end == len(s):
start=start+1
end=start+1
if len(ans)!=0:
return max(ans)
else:
return 0
修改一下while部分,在倒数50个左右超时了,因为每次都要执行第一个while,非常耗时,但是算法本身没错
while start <len(s)-1:
if A[s[start]] !=1:
start=start+1
end=start+1
continue
if A[s[end]] !=2:
end=end+1
if end == len(s):#多加了这一部分,用来判断end的边界
start=start+1
end=start+1
continue
ans.append(yxkh(s[start:end+1]))
end=end+1
if end == len(s):
start=start+1
end=start+1
最后我尝试加一行,用来判断是偶数的符号串才加入计算,的快了一半,但是还是超时了:
if len(s[start:end+1])> max(ans) and len(s[start:end+1])%2==0:
if yxkh(s[start:end+1]) != 0 :
ans.append(yxkh(s[start:end+1]))
我再一次更改代码,换了一种思路,计算切片中’(‘和’)‘的个数,只有遍历片段时’(‘大于等于’)'时,才有可能是有效片段,在倒数10个测试中超时了
while start <len(s)-1:
if s[start] !='(':
start=start+1
continue
num_1=1
en=1
while start+en<len(s):
if s[start+en]=='(':
num_1+=1
else:
num_2+=1
if num_1==num_2 and s[start+en]==')':#粗略的计算可能有效的片段
if en+1<max(ans):
en+=1
continue
ans.append(yxkh(s[start:start+en+1]))
en=en+1
if len(s[start:])<max(ans):#如果需要遍历的s小于ansl,就结束遍历
break
start=start+1
num_2=0
return max(ans)
我反应过来,这题并不需要判断是否为有效符号串的函数,因为只有一种括号,所以并不需要函数来判断是否有效,通过个数就可以判断
我尝试修改最里面的while函数,并且删除yxkh函数,直接使用字符串长度,在倒数第二个超时了,因为如果s的开头是’(((((…‘时,每次都要从一个’('遍历一遍,非常耗时
if len(s)<=1:
return 0
ans=[0]
num_2=0
start=0
while start <len(s)-1:
if s[start] !='(': #每个有效串都以'('开头
start=start+1
continue
num_1=1
en=1
while start+en<len(s):
if s[start+en]=='(':
num_1+=1
else:
num_2+=1
if num_1<num_2:#如果成立,那么从start之后的s都不是有效括号
break
if num_1==num_2 and s[start+en]==')':
if en+1<max(ans):
en+=1
continue
ans.append(en+1) #直接保存这个有效串的长度
en=en+1
if len(s[start:])<max(ans):
break
start=start+1
num_2=0
return max(ans)
因我担心漏掉一个’('可能会丢失最佳长度,所以每次start都加1,非常耗时,而且容易重复计算一些本就无效的序列
最后再次尝试修改,只遍历一遍,为什么就不怕丢失呢,思想就是把整个s分割成很多个有效括号串的排列,排列过程中会遇到多余的括号,那么我们只需要把有效串连续排列最大长度找出来就好了。刚才说的无效的序列就是包括多余括号的几个有效串,其实也是无效的
if len(s)<=1:
return 0
ans=[]
mm=0
st=0
for i in range(len(s)):#是为了记录下标i
if s[i]=='(':
ans.append(i)
else:
if ans==[]:#即前面没有'(',比如'))(...'时,显然不会有效
st=i+1#那么把可能有效序列开始的下标设为它后面的一位
#st之前的最大已经计算
continue
else:#当出现')'时,在ans中可以配对,就在ans中pop
ans.pop()
#只要pop依次就要尝试更新mm
if ans==[]:#如果为空,则表明这是一个最大字符串,从st到i
#这里的st指代第一个'(',继续下一轮的迭代,此时
#的最大串是从st开始的,st不变
mm=max(mm,i-st+1)#出现一个最大括号串
else:#如果不为空,i-ans[-1]指的是目前这个子串的长度
#比如'(()' i-ans[-1]就表示其中的'()'
#比如'((()()()()',i-ans[-1]就是'()()()()'
mm=max(mm,i-ans[-1])
return mm