給出 n 代表生成括號的對數,請你寫出乙個函式,使其能夠生成所有可能的並且有效的括號組合。
例如,給出 n = 3,生成結果為:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
回溯演算法可以用來窮盡複雜、遞迴問題的所有解。一般地,當遇到需要求出所有可能解的問題時,可以考慮從回溯(dfs)思想入手。
可以很容易地得出,遞迴深度depth
跟括號對數n
有關:depth = 2 * n
。
如果不考慮**「有效性」**而只考慮左右括號數量對等的話,一共有c2n
nc_^
c2nn
種括號組合:
class
solution};
list
output =
newarraylist
<
>()
;backtrace
(output, braces,"",
2* n,1)
;return output;
}/**
* @param restbraces:hashmap剩餘的括號數量
* @param possible:string 表示一種可能的解
* @param n:int 最大遞迴深度
* @param depth:int 遞迴深度
*/private
void
backtrace
(list
output, hashmap
restbraces, string possible,
int n,
int depth)
for(
char brace : restbraces.
keyset())}}
但若要考慮**「有效性」的話,則需要從所有可能中剔除無效組合**(剪枝)。那麼什麼樣的情況是無效的呢?
如果當前附加的字元為)
的話:
class
solution};
list
output =
newarraylist
<
>()
;backtrace
(output, braces,"",
2* n,1)
;return output;
}/**
* @param restbraces:hashmap剩餘的括號數量
* @param possible:string 表示一種可能的解
* @param n:int 最大遞迴深度
* @param depth:int 遞迴深度
*/private
void
backtrace
(list
output, hashmap
restbraces, string possible,
int n,
int depth)
for(
char brace : restbraces.
keyset()
) restbraces.
put(brace, restbraces.
get(brace)-1
);backtrace
(output, restbraces, possible + brace, n, depth +1)
;// backtrace
restbraces.
put(brace, restbraces.
get(brace)+1
);}}
}
難受啊,為什麼只擊敗了10 ~ 20%的提交啊~~還有什麼地方可以優化的麼?
只有在我們知道序列仍然保持有效時才新增'('
or')'
。我們可以通過跟蹤到目前為止放置的左括號和右括號的數目來做到這一點。
LeetCode 22 生成括號
22 生成括號 給出 n 代表生成括號的對數,請你寫出乙個函式,使其能夠生成所有可能的並且有效的括號組合。例如,給出 n 3,生成結果為 生成所有 2 個 和 字元構成的序列。然後,我們將檢查每乙個是否有效。為了檢查序列是否為有效的,我們會跟蹤平衡,也就是左括號的數量減去右括號的數量的淨值。如果這個...
Leetcode演算法 22 生成括號字串
給定整數n,要求輸出 n 對左右括號的所有可能的有效組合。示例 輸入 n 3 輸出 為了保證括號字串是有效的,需要滿足兩個條件 可以使用遞迴法,來保證這兩個條件,步驟如下 1 起始有 n 個左括號和 n 個右括號需要拼接到字串中。2 先將結果字串初始化為空。3 每次遞迴時,選擇其中一種括號,拼接到結...
leetcode 22 生成合法的括號組合
給定n對括號,計算出n對括號的所有合法組合 實現起來非常複雜 將每一種括號的組合放在6個字元大小的陣列中,共會產生22n個組合,時間複雜度位2 2n 如何判斷非法括號組合 從左往後掃瞄,當左括號出現次數少於右括號時即非法,如 還是遞迴,但使用剪枝法來排除產生非法的括號組合 左括號可以隨便新增,最多到...