Leetcode做題日記:32. 最長有效括號 (PYTHON)
阿新 • • 發佈:2019-01-01
給定一個只包含 ‘(’ 和 ‘)’ 的字串,找出最長的包含有效括號的子串的長度。
示例 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