难度:中等
目录
一、问题描述
这里直接采用LeetCode上面的描述。
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
下面给出示例:
提示:
1 <= n <= 8
二、思路
1、解题思路
这里题目就是给我们 n 个 ' ( ' 和 ' ) ' ,让我们进行排列组合,保留符合括号匹配的答案,因此我们可以用 DFS 排列出所有的排列组合,但是其中有不符合要求的答案,因此我们要进行 剪枝 操作,将不符合题目要求的枝 减去,这样 DFS 到最终 只留下符合要求的 答案。
因此我们可以开始观察
当( n == 1 ):
我们可以看到上图,要满足要求题目要求,必须先保存 ' ( ',即 左括号数量必须 >= 右括号数量 。我们可以知道结束 DFS 的条件为: 左括号 == n && 右括号 == n。
当( n == 2 ):
观察上图,我们可以看到符合要求的分支都是:
- 左括号数量 >= 右括号数量
- 当左右括号数量相等时,优先 添加 ' ( ',才能继续满足 条件1。
综上所述,我们可以完成 DFS剪枝 的条件。
每次递归都往 str 中添加一个括号,并且更新 左括号 或 右括号 的数量,再进行下一次递归,直至左右括号都达到最大数量停止 递归 开始 回溯。
三、解题
1、代码实现
class Solution {
public:
// n 为一对括号的数量(左括号和右括号的最大数量),left 为左括号的数量,right 为右括号的数量,str为递归的字符串
void DFS(int n, int left, int right, string str){
//递归停止条件:满足要求,将答案保存
if(left == n && right == n){
ans.push_back(str);
}
//不满足停止递归条件 即 进行剪枝操作,只保留符合要求的树枝
else{
//当左括号 数量小于 左括号的最大数量时,可以添加 '('
if(left < n){
DFS(n,left+1,right,str+'(');
}
//右括号数量小于左括号数量时 ,可以添加 ')'
if(right < left){
DFS(n,left,right+1,str+')');
}
}
}
vector<string> generateParenthesis(int n) {
string str = "";
DFS(n, 0, 0, str);
return ans;
}
private:
vector<string> ans;
};
2、时间复杂度 and 空间复杂度
时间复杂度:
空间复杂度:
四、总结
这一题对我来说还是比较难的,刚开始没想到用的 DFS 后来看了题解恍然大悟,还能有这种解法,刚开始的思路是:将所有的有效组合全部排列出来,再从排列组合中去选取满足题目要求的 答案保存下来。
以后碰到类似的题,要在排列组合中 将不符合要求的筛选掉,使用的就是 DFS + 剪枝 的操作,不断的减去不符合要求的枝叶,直至结束递归 剩下的就是符合要求的。