题目:22. 括号生成
解答:这道题是继17题以后再次遇到回溯相关的内容,实际上还是非常不熟练,需要继续加强。这道题的解法众多,其中有很多看得我一头雾水,最终找到了一个容易理解的讲解,原链接为:https://leetcode.cn/problems/generate-parentheses/solutions/597236/sui-ran-bu-shi-zui-xiu-de-dan-zhi-shao-n-0yt3
首先我们明确,我们需要生成有2*n个元素的括号序列(先不考虑左右括号的配对),那么所有结果我们可以用一个树形图来表示:
接下来就是对于所有结果的筛选了,从而得到满足我们要求的结果,即能够完全配对的结果。
1、首先我们需要筛选掉有大于n个左括号或者右括号的结果,因为这样不可能出现n对括号。因此我们使用left来记录左括号的个数,用right记录生成右括号的个数,当left > n 或者 right > n时,就不再继续。
2、其次我们发现,如果生成过程中右括号的个数大于左括号,那一定是错误的,比如有2个左括号,3个右括号,那么一定无法成功匹配,因此当right > left时,也不再继续。
这时我们可以发现,生成过程中right一定小于left,而left又小于n,因此right也一定小于n,因此right < n的条件我们可以省略。
代码如下:
class Solution {
public:
vector<string> res;
string path;
int n1;
void Backtracking(string path, int left, int right){
if(left>n1 || right>left) return;
if(path.size()== 2*n1){
res.push_back(path);
return;
}
path.push_back('(');
Backtracking(path, left+1,right);
path.pop_back();
path.push_back(')');
Backtracking(path,left,right+1);
path.pop_back();
}
vector<string> generateParenthesis(int n) {
n1=n;
if(n==0) return res;
Backtracking(path,0,0);
return res;
}
};
虽然一眼看上去不符合回溯算法的经典模板,但其实处理方式都是一样的;此外以下两句代码也可以合并成一句。
path.push_back('(');
Backtracking(path, left+1,right);
//合并为:Backtracking(path + ‘(’, left+1,right);
但看到有人提到,这样会产生一个临时对象,不得不说考虑的好细呀。