iT邦幫忙

0

leetcode with python:22. Generate Parentheses

  • 分享至 

  • xImage
  •  

題目:

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

給定一數n,回傳所有n個括號的排列可能(括號需有對應,像")("就不行)

我發現只要在n-1個括號的所有排列可能裡所有的"("後加上"()"
再特別考慮"()()()..."這種可能,就考慮到了n個括號的所有排列可能
ex:n=2,所有可能會是["()()"和"(())"]
"()()"=>"(())()","()(())"
"(())"=>"(()())","((()))"
特別考慮=>"()()()"
而n=3的所有可能即為["((()))","(()())","(())()","()(())","()()()"]

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans=["()"]
        
        for i in range(n-1):
            temp=[]
            temp.append(ans[0]+"()")
            for j in range(len(ans)):
                for k in range(len(ans[j])):
                    if ans[j][k]=="(":
                        t=ans[j][0:k+1]+"()"+ans[j][k+1:len(ans[j])]
                        if t not in temp:
                            temp.append(t)
            ans=temp
                 
        return ans

以初始陣列["()"]出發推斷出後續可能
第一項固定放"()()()...."類型的組合
所以先將紀錄前一次所有可能的陣列(ans)的第一項後加上"()"
放入紀錄此次所有可能的陣列(temp)

接著將ans內裡所有元素一一操作
在"("後加上"()"放入temp內
但為防止重複紀錄,先確認該可能不在temp內後再加入
完全執行完後將ans變為temp,進入下一次迴圈
迴圈執行結束後回傳ans
最後執行時間114ms(faster than 5.07%)

然而我的解法效率低落,於是我開始瀏覽討論區
看到了下面這個解法

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        ans=[]
        temp=[]
        
        def x(opencnt,closecnt):
            if opencnt==closecnt==n:
                ans.append("".join(temp))
                return
            
            if opencnt<n:
                temp.append("(")
                x(opencnt+1,closecnt)
                temp.pop()
                
            if closecnt<opencnt:
                temp.append(")")
                x(opencnt,closecnt+1)
                temp.pop()
        
        x(0,0)
        return ans

是個遞迴解,紀錄目前使用的"("和")"個數來繼續推測接下來的可能

我們最多可以使用n個"("和n個")"來排列可能
而排列過程中絕不能使")"的使用次數(closecnt)超過"("的使用次數(opencnt)
否則會造成不合理的組合出現(如:")(","())(()")

所以當我們決定下一個括號要排什麼時
只要opencnt< n我們下一項就可以選擇放"("
而當closecnt< opencnt我們又多了")"可以選擇

函式(x)需要的輸入資料即opencnt和closecnt
當前的排列順序都記錄在temp
當opencnt==closecnt==n時,代表這時temp內裝的是其中一種可能
將其透過join變為字串後放入ans,return

而當opencnt< n,我們選擇放"("至temp內
往下執行x(opencnt+1,closecnt)繼續探索此排列之後的可能
執行結束後將剛填入的"("pop掉(此排列之後的可能已全部被探索且記錄)

而又當closecnt< opencnt,我們選擇放")"至temp內
往下執行x(opencnt,closecnt+1)繼續探索此排列之後的可能
執行結束後將剛填入的")"pop掉(此排列之後的可能已全部被探索且記錄)

執行x(0,0),結束後ans內已有所有n個括號的排列可能
回傳ans
最後執行時間34ms(faster than 95.21%)

那我們下題見


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言