括号生成,力扣上原题,有一些疑惑

class Solution {
void backtrack(vector& ans, string& cur, int open, int close, int n) {
if (cur.size() == n * 2) {
ans.push_back(cur);
return;
}
if (open < n) {
cur.push_back('(');
backtrack(ans, cur, open + 1, close, n);
cur.pop_back();
}
if (close < open) {
cur.push_back(')');
backtrack(ans, cur, open, close + 1, n);
cur.pop_back();
}
}
public:
vector generateParenthesis(int n) {
vector result;
string current;
backtrack(result, current, 0, 0, n);
return result;
}
};
问:来一个认真负责的大佬,详细列举举例一下回溯的过程,我一直不停的推导void backtrack,例如n=3,我只得到了((()))一个结果,希望详细一点
力扣上的原题的官方解析,回溯法,来一个认真负责的大佬


#include <vector>
#include <string>
#include <iostream>
using namespace std;

class Solution
{
    void backtrack(vector<string> &ans, string &cur, int open, int close, int n)
    {
        if (cur.size() == n * 2)
        {
            ans.push_back(cur);
            return;
        }
        if (open < n)
        {
            cur.push_back('(');
            cout << cur << endl;
            backtrack(ans, cur, open + 1, close, n);
            cur.pop_back();
            cout << cur << endl;
        }
        if (close < open)
        {
            cur.push_back(')');
            cout << cur << endl;
            backtrack(ans, cur, open, close + 1, n);
            cur.pop_back();
            cout << cur << endl;
        }
    }

public:
    vector<string> generateParenthesis(int n)
    {
        vector<string> result;
        string current;
        backtrack(result, current, 0, 0, n);
        return result;
    }
};

int main(void)
{
    Solution su;
    vector<string> r = su.generateParenthesis(2);
    cout << "result is: " << endl;
    for (int i = 0; i < r.size(); ++i)
    {
        cout << r[i] << endl;
    }
    return 0;
}

打印每个步骤看一下:
以n=2为例子:
1.
current = ""
backtrack(result, current, 0, 0, 2);

2.
open = 0, close = 0
current = "("
backtrack(result, current, 1, 0, 2); --> 进入if(open < n)内的backtrack

3.
open = 1, close = 0
current = "(("
backtrack(result, current, 2, 0, 2); --> 进入if(open < n)内的backtrack

4.
open = 2, close = 0
current = "(()"
backtrack(ans, cur, 2, 1, 2); --> 进入if(close < open)内的backtrack

5.
open = 2, close = 1
current = "(())"
backtrack(ans, cur, 2, 2, 2); --> 进入if(close < open)内的backtrack

6.
open = 2, close = 2
此时current.size() == 4
执行 ans.push_back(cur); --> 得到第一个合格字符串"(())"

  1. 继续执行第5步

    if (close < open) {
    cur.push_back(')');
    backtrack(ans, cur, open, close + 1, n);
    cur.pop_back();
    }
    

    current = "(()"

  2. 继续执行第4步

    if (close < open) {
    cur.push_back(')');
    backtrack(ans, cur, open, close + 1, n);
    cur.pop_back();
    }
    

    current = "(("

  3. 继续执行第3步

    if (open < n) {
    cur.push_back('(');
    backtrack(ans, cur, open + 1, close, n);
    cur.pop_back();
    }
    

    current = "("

并且第3步中: open = 1, close = 0, close < open
执行

cur.push_back(')');
backtrack(ans, cur, open, close + 1, n);

current = "()"
backtrack(ans, cur, 1, 1, 2) --> 进入if(close < open)内的backtrack

10.
open = 1, close = 1
current = "()("
backtrack(ans, cur, 2, 1, 2); --> 进入if(open < n)内的backtrack

11.
open = 2, close = 1
current = "()()"
backtrack(ans, cur, 2, 2, 2) --> 进入if(close < open)内的backtrack

13.
open = 2, close = 2
此时current.size() == 4
执行 ans.push_back(cur); --> 得到第二个合格字符串"()()"

这个用语言很难解释,你用ide,debug一下就会比较清楚。当左括号数小于n时,可以选择继续加左括号(尝试加完会回溯,变成没有加的状态);当右括号数小于左括号数时可以继续加右括号(尝试加完会回溯,变成没有加的状态)。

这么巧么,今天我也刚做过这道,也是用的回溯,C++不大懂,C#做的
思路也是类似的

public class Solution {
    List<string> list=new List<string>();
    public IList<string> GenerateParenthesis(int n) {
        AAA("",n,0);
        return list;
    }
    public void AAA(string str, int left,int right)
    {
        if(left==0&&right==0)
            list.Add(str);
        if(left>0)
        {
            string Lstr= str+"(";
            AAA(Lstr,left-1,right+1);
        }
        if(right>0)
        {
            string Rstr= str+")";
            AAA(Rstr,left,right-1);
        }
    }
}

img


这个说实话很难描述(可能我表达能力不行),我把这个过程打印出来,每一次执行条件2或3我就debug一次,****则是符合条件1

img