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

猜你喜欢

转载自blog.csdn.net/weixin_44033136/article/details/85530907