LeetCode Notes_#22_括號生成
阿新 • • 發佈:2020-11-03
LeetCode Notes_#22_括號生成
LeetCodeContents
題目
解答
方法1:暴力遞迴
給出括號對數n
之後,就確定了括號組合的字串長度必然是2n
,我們可以通過暴力遞迴的方式,在2n
個位置上放置'('或者')',得到所有的排列序列,然後逐個判斷每個排列序列是否是正確的,將正確的排列序列加入到結果列表當中。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> combinations = new ArrayList<>();
generateAll(new char[2*n], 0, combinations);
return combinations;
}
public void generateAll(char[] current, int pos, List<String> result){
//出口條件:pos指標指向current的末尾之後一個位置(末尾是current.length - 1)
if(pos == current.length){
if (valid(current)){
result.add(new String(current));
}
//遞推過程:在current陣列末尾位置新增'('或者')',然後進行遞迴呼叫,在下一個位置pos + 1繼續新增'('或者')'
//這個過程中並不考慮'('和')'之間的數量以及配對是否是正確的,而是在將整個字串都生成後,才判斷這個字串是否是正確配對的
}else{
current[pos] = '(';
generateAll(current, pos + 1 , result);
current[pos] = ')';
generateAll(current, pos + 1, result);
}
}
//驗證一個排列序列是否正確
public boolean valid(char[] current){
int balance = 0;
for(char c: current){
if(c == '('){
balance++;
}else{
balance--;
}
if(balance < 0){
return false;
}
}
return balance == 0;
}
}
複雜度分析
時間複雜度:,排列序列一共有個,對於每個排列序列,呼叫valid()
方法進行驗證,其時間複雜度為。
空間複雜度:,遞迴棧的深度是2n層。
方法2:回溯
在暴力遞迴法當中,我們其實生成了很多無效的排列序列,但是都要等到最後才能判斷出它們是無效的。更優的方法應該是在構造序列的時候,就進行剪枝,對於已經確認無效的序列,提前將其排除(剪枝)。
回溯法裡邊的回溯,指的就是撤銷選擇這一過程,無論這一次選擇的結果是不是正確的,我們都需要回溯回去,嘗試其他的可能性。
class Solution {
public List<String> generateParenthesis(int n) {
List<String> ans = new ArrayList<>();
backtrack(ans, new StringBuilder(), 0, 0, n);
return ans;
}
// left,right代表左括號,右括號出現的次數
private void backtrack(List<String> ans, StringBuilder cur, int left, int right, int n){
//出口條件:長度達到2n,可以保證結果是正確的,直接加入結果列表當中
if(cur.length() == 2*n){
ans.add(cur.toString());
return;
}
//左括號數量<n,可以繼續新增左括號
if(left < n){
cur.append('(');
backtrack(ans, cur, left + 1, right, n);
cur.deleteCharAt(cur.length() - 1);
}
//右括號的數量<左括號的數量,可以繼續新增右括號
if(right < left){
cur.append(')');
backtrack(ans, cur, left, right + 1, n);
cur.deleteCharAt(cur.length() - 1);
}
}
}