給出 n 代表生成括號的對數,請你寫出一個函數,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果爲:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
思路: 回溯法
非常牛逼的講解,需要這樣的人來給我們講算法
以Generate Parentheses爲例,backtrack的題到底該怎麼去思考?
所謂Backtracking都是這樣的思路:在當前局面下,你有若干種選擇。那麼嘗試每一種選擇。如果已經發現某種選擇肯定不行(因爲違反了某些限定條件),就返回;如果某種選擇試到最後發現是正確解,就將其加入解集
所以你思考遞歸題時,只要明確三點就行:選擇 (Options),限制 (Restraints),結束條件 (Termination)。即“ORT原則”(這個是我自己編的)
對於這道題,在任何時刻,你都有兩種選擇:
- 加左括號。
- 加右括號。
同時有以下限制:
- 如果左括號已經用完了,則不能再加左括號了。
- 如果已經出現的右括號和左括號一樣多,則不能再加右括號了。因爲那樣的話新加入的右括號一定無法匹配。
結束條件是:
左右括號都已經用完。
結束後的正確性:
左右括號用完以後,一定是正確解。因爲1. 左右括號一樣多,2. 每個右括號都一定有與之配對的左括號。因此一旦結束就可以加入解集(有時也可能出現結束以後不一定是正確解的情況,這時要多一步判斷)。
遞歸函數傳入參數:
限制和結束條件中有“用完”和“一樣多”字樣,因此你需要知道左右括號的數目。
當然你還需要知道當前局面sublist和解集res。
因此,把上面的思路拼起來就是代碼:
if (左右括號都已用完) {
加入解集,返回
}
//否則開始試各種選擇
if (還有左括號可以用) {
加一個左括號,繼續遞歸
}
if (右括號小於左括號) {
加一個右括號,繼續遞歸
}
你帖的那段代碼邏輯中加了一條限制:“3. 是否還有右括號剩餘。如有才加右括號”。這是合理的。不過對於這道題,如果滿足限制1、2時,3一定自動滿足,所以可以不判斷3。
這題其實是最好的backtracking初學練習之一,因爲ORT三者都非常簡單明顯。你不妨按上述思路再梳理一遍,還有問題的話再說。
以上文字來自 1point3arces的牛人解答
複雜度分析
我們的複雜度分析依賴於理解 generateParenthesis(n) 中有多少個元素。這個分析超出了本文的範疇,但事實證明這是第 n 個卡塔蘭 數.
時間複雜度:O(4^n/sqrt(n)),在回溯過程中,每個有效序列最多需要 n 步。
空間複雜度:O(4^n/sqrt(n)),並使用O(n) 的空間來存儲序列。
class Solution:
def generateParenthesis(self, n):
# if n == 0: return ''
self.res = []
self.gen('', n, n)
return self.res
import pysnooper
@pysnooper.snoop()
def gen(self, sub, left, right):
if left == 0 and right == 0:
self.res.append(sub)
return
if left > 0:
self.gen(sub+'(', left-1, right)
if right > left:
self.gen(sub+')', left, right-1)
s.generateParenthesis(3)
Starting var:.. left = 3
Starting var:.. right = 3
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = ''
21:24:19.191288 call 9 def gen(self, sub, left, right):
21:24:19.193285 line 10 if left == 0 and right == 0:
21:24:19.193285 line 14 if left > 0:
21:24:19.194286 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 2
Starting var:.. right = 3
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '('
21:24:19.194286 call 9 def gen(self, sub, left, right):
21:24:19.194286 line 10 if left == 0 and right == 0:
21:24:19.196285 line 14 if left > 0:
21:24:19.196285 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 1
Starting var:.. right = 3
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(('
21:24:19.197284 call 9 def gen(self, sub, left, right):
21:24:19.197284 line 10 if left == 0 and right == 0:
21:24:19.197284 line 14 if left > 0:
21:24:19.197284 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 0
Starting var:.. right = 3
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '((('
21:24:19.202280 call 9 def gen(self, sub, left, right):
21:24:19.202280 line 10 if left == 0 and right == 0:
21:24:19.203282 line 14 if left > 0:
21:24:19.203282 line 16 if right > left:
21:24:19.203282 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '((()'
21:24:19.204280 call 9 def gen(self, sub, left, right):
21:24:19.204280 line 10 if left == 0 and right == 0:
21:24:19.204280 line 14 if left > 0:
21:24:19.204280 line 16 if right > left:
21:24:19.204280 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '((())'
21:24:19.204280 call 9 def gen(self, sub, left, right):
21:24:19.205280 line 10 if left == 0 and right == 0:
21:24:19.205280 line 14 if left > 0:
21:24:19.205280 line 16 if right > left:
21:24:19.205280 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 0
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '((()))'
21:24:19.205280 call 9 def gen(self, sub, left, right):
21:24:19.205280 line 10 if left == 0 and right == 0:
21:24:19.205280 line 11 self.res.append(sub)
21:24:19.205280 line 12 return
21:24:19.205280 return 12 return
Return value:.. None
21:24:19.205280 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.206278 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.206278 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.207278 line 16 if right > left:
21:24:19.207278 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 1
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(()'
21:24:19.207278 call 9 def gen(self, sub, left, right):
21:24:19.207278 line 10 if left == 0 and right == 0:
21:24:19.207278 line 14 if left > 0:
21:24:19.208277 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 0
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(()('
21:24:19.208277 call 9 def gen(self, sub, left, right):
21:24:19.209282 line 10 if left == 0 and right == 0:
21:24:19.209282 line 14 if left > 0:
21:24:19.209282 line 16 if right > left:
21:24:19.209282 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(()()'
21:24:19.209282 call 9 def gen(self, sub, left, right):
21:24:19.209282 line 10 if left == 0 and right == 0:
21:24:19.210275 line 14 if left > 0:
21:24:19.210275 line 16 if right > left:
21:24:19.210275 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 0
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(()())'
21:24:19.210275 call 9 def gen(self, sub, left, right):
21:24:19.210275 line 10 if left == 0 and right == 0:
21:24:19.210275 line 11 self.res.append(sub)
21:24:19.210275 line 12 return
21:24:19.210275 return 12 return
Return value:.. None
21:24:19.210275 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.211275 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.211275 line 16 if right > left:
21:24:19.211275 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 1
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(())'
21:24:19.211275 call 9 def gen(self, sub, left, right):
21:24:19.211275 line 10 if left == 0 and right == 0:
21:24:19.211275 line 14 if left > 0:
21:24:19.211275 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 0
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(())('
21:24:19.212275 call 9 def gen(self, sub, left, right):
21:24:19.212275 line 10 if left == 0 and right == 0:
21:24:19.212275 line 14 if left > 0:
21:24:19.212275 line 16 if right > left:
21:24:19.212275 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 0
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '(())()'
21:24:19.212275 call 9 def gen(self, sub, left, right):
21:24:19.212275 line 10 if left == 0 and right == 0:
21:24:19.214273 line 11 self.res.append(sub)
21:24:19.214273 line 12 return
21:24:19.214273 return 12 return
Return value:.. None
21:24:19.215273 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.215273 line 16 if right > left:
21:24:19.215273 return 16 if right > left:
Return value:.. None
21:24:19.215273 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.215273 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.216273 line 16 if right > left:
21:24:19.216273 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 2
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()'
21:24:19.216273 call 9 def gen(self, sub, left, right):
21:24:19.216273 line 10 if left == 0 and right == 0:
21:24:19.217273 line 14 if left > 0:
21:24:19.217273 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 1
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()('
21:24:19.217273 call 9 def gen(self, sub, left, right):
21:24:19.217273 line 10 if left == 0 and right == 0:
21:24:19.218271 line 14 if left > 0:
21:24:19.218271 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 0
Starting var:.. right = 2
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()(('
21:24:19.227267 call 9 def gen(self, sub, left, right):
21:24:19.227267 line 10 if left == 0 and right == 0:
21:24:19.228265 line 14 if left > 0:
21:24:19.228265 line 16 if right > left:
21:24:19.228265 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()(()'
21:24:19.228265 call 9 def gen(self, sub, left, right):
21:24:19.228265 line 10 if left == 0 and right == 0:
21:24:19.228265 line 14 if left > 0:
21:24:19.229264 line 16 if right > left:
21:24:19.229264 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 0
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()(())'
21:24:19.229264 call 9 def gen(self, sub, left, right):
21:24:19.229264 line 10 if left == 0 and right == 0:
21:24:19.229264 line 11 self.res.append(sub)
21:24:19.229264 line 12 return
21:24:19.230264 return 12 return
Return value:.. None
21:24:19.232263 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.233262 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.233262 line 16 if right > left:
21:24:19.233262 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 1
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()()'
21:24:19.233262 call 9 def gen(self, sub, left, right):
21:24:19.235261 line 10 if left == 0 and right == 0:
21:24:19.235261 line 14 if left > 0:
21:24:19.235261 line 15 self.gen(sub+'(', left-1, right)
Starting var:.. left = 0
Starting var:.. right = 1
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()()('
21:24:19.235261 call 9 def gen(self, sub, left, right):
21:24:19.235261 line 10 if left == 0 and right == 0:
21:24:19.235261 line 14 if left > 0:
21:24:19.235261 line 16 if right > left:
21:24:19.235261 line 17 self.gen(sub+')', left, right-1)
Starting var:.. left = 0
Starting var:.. right = 0
Starting var:.. self = <__main__.Solution object at 0x0000014A63D8D668>
Starting var:.. sub = '()()()'
21:24:19.236261 call 9 def gen(self, sub, left, right):
21:24:19.236261 line 10 if left == 0 and right == 0:
21:24:19.236261 line 11 self.res.append(sub)
21:24:19.237260 line 12 return
21:24:19.237260 return 12 return
Return value:.. None
21:24:19.237260 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.237260 line 16 if right > left:
21:24:19.237260 return 16 if right > left:
Return value:.. None
21:24:19.237260 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.238259 line 16 if right > left:
21:24:19.238259 return 16 if right > left:
Return value:.. None
21:24:19.238259 return 17 self.gen(sub+')', left, right-1)
Return value:.. None
21:24:19.238259 line 16 if right > left:
21:24:19.238259 return 16 if right > left:
Return value:.. None
['((()))', '(()())', '(())()', '()(())', '()()()']