1. 程式人生 > >Leetcode做題日記:32. 最長有效括號 (PYTHON)

Leetcode做題日記:32. 最長有效括號 (PYTHON)

給定一個只包含 ‘(’ 和 ‘)’ 的字串,找出最長的包含有效括號的子串的長度。
示例 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