22. 括号生成(回溯+剪枝)
Posted Ston.V
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了22. 括号生成(回溯+剪枝)相关的知识,希望对你有一定的参考价值。
1.Description
数字
n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
2.Example
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:输入:n = 1
输出:["()"]
3.My Code
回溯的办法,来遍历所有由括号组成的结果,然后判断是否合法,这里没有一点剪枝。
class Solution
public:
bool isLeagal(string s)
vector<char> v;
for(int i=0;i<s.length();i++)
if(v.size()!=0 && (v.back()=='(' && s[i]==')'))
v.pop_back();
continue;
v.push_back(s[i]);
if(v.size()==0)
return true;
return false;
void DFS(vector<string>&vs,string &s,int lb,int rb,int n)
if(s.length() == 2*n )
if(isLeagal(s))
vs.push_back(s);
return;
//add left beacket
if(lb <n)
s.push_back('(');
DFS(vs,s,lb+1,rb,n);
s.pop_back();
if(rb <n)
s.push_back(')');
DFS(vs,s,lb,rb+1,n);
s.pop_back();
return;
vector<string> generateParenthesis(int n)
vector<string> vs;
string s="";
DFS(vs,s,0,0,n);
return vs;
;
4.Code
同样是回溯的办法,但是通过观察发现规律:如果左括号数量不大于 n,我们可以放一个左括号。如果右括号数量小于左括号的数量,我们可以放一个右括号。即左括号数目总是要不小于右括号数目,于是对于右括号的放置可以剪枝,同时这样得到的一定是合法的,避免合法检测。
class Solution
public:
void DFS(vector<string>&vs,string &s,int lb,int rb,int n)
if(s.length() == 2*n )
vs.push_back(s);
return;
//add left bracket when lb < n
if(lb <n)
s.push_back('(');
DFS(vs,s,lb+1,rb,n);
s.pop_back();
//add right bracket when rb < lb
if(rb <lb)
s.push_back(')');
DFS(vs,s,lb,rb+1,n);
s.pop_back();
return;
vector<string> generateParenthesis(int n)
vector<string> vs;
string s="";
DFS(vs,s,0,0,n);
return vs;
;
5.注意
1.这个括号符合规则的判断也可以优化,计数器遇到左括号加一,遇到右括号减一,当计数器为负,则非法。
2.对于剪枝条件,需要注意放置规律:必须左括号数目不小于右括号数目
3.对于回溯写法:注意回溯格式,我们for循环的应当是进展到某一步的不同方向的下一步操作。
以上是关于22. 括号生成(回溯+剪枝)的主要内容,如果未能解决你的问题,请参考以下文章