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); --> 得到第一个合格字符串"(())"
继续执行第5步
if (close < open) {
cur.push_back(')');
backtrack(ans, cur, open, close + 1, n);
cur.pop_back();
}
current = "(()"
继续执行第4步
if (close < open) {
cur.push_back(')');
backtrack(ans, cur, open, close + 1, n);
cur.pop_back();
}
current = "(("
继续执行第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);
}
}
}