题目描述
数字 n
代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3 输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1 输出:["()"]
提示:
1 <= n <= 8
题目解析
解题思路
本题要求生成所有可能的合法括号组合,可以通过回溯(Backtracking)算法来解决。回溯算法通过递归的方式,逐步构建合法的括号序列。当满足特定条件时,保存当前构建的序列;否则,继续尝试添加括号或回退到上一步。
具体思路如下:
-
定义初始条件:
- 一共有
n
对括号,因此最终序列的长度为2 * n
。 - 设定两个变量:
left
表示剩余可用的左括号数,right
表示当前序列中可用的右括号数。
- 一共有
-
递归回溯的条件:
- 如果当前已构建序列的长度
i
达到2 * n
,则说明构建完成,保存当前序列。 - 如果当前序列中还有剩余的右括号(
right > 0
),可以添加一个右括号。 - 如果还有剩余的左括号(
left > 0
),则可以添加一个左括号,并且递归调用后,right
增加1(因为在合法括号序列中,右括号数量不应超过已用左括号数量)。
- 如果当前已构建序列的长度
-
剪枝条件:
- 在任何递归状态下,不能在左括号数(
left
)为0时继续放置右括号,否则生成的括号组合将不合法。
- 在任何递归状态下,不能在左括号数(
-
终止条件:
- 递归结束的标志是序列长度达到
2 * n
,此时将生成的序列加入结果集。
- 递归结束的标志是序列长度达到
class Solution {
public:
// 在任何一个位置的左边,左括号不能多于右括号
// 在任何一个位置,不放左括号就必须要放右括号
void backtrack(int i, int n, int left, int right, string &pre, vector<string> &res) {
if (i == n) {
res.emplace_back(pre);
return;
}
if (right) {
pre.push_back(')');
backtrack(i + 1, n, left, right - 1, pre, res);
pre.pop_back();
}
if (left) {
pre.push_back('(');
backtrack(i + 1, n, left - 1, right + 1, pre, res);
pre.pop_back();
}
}
vector<string> generateParenthesis(int n) {
string pre = "";
vector<string> res;
backtrack(0, 2 * n, n, 0, pre, res);
return res;
}
};