数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
1 <= n <= 8
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/generate-parentheses
思路:因为数据量比较小,而且做过判断括号是否合法的题,所以最先想到的就是生成括号序列后,判断是否合法。
class Solution {
private:
//存储最终结果
vector res;
//判断括号是否合法
bool isVaild(string s){
stack st;
for(int i = 0;i generateParenthesis(int n) {
//2*n个位置
myslove(0,"",2*n);
return res;
}
};
结果发现,好慢,而且内存消耗大。
思路:然后思考,那么是不是可以有些情况不用去搜索呢(剪枝)?然后发现,左括号和右括号数量是一定的,那么,当左括号或右括号大于n时,就不用再继续搜下去了(剪枝1)。同时,当剩余的左括号数大于右括号数时,也一定不合法(剪枝2)。
class Solution {
private:
vector res;
//判断是否合法。
bool isVaild(string s){
stack st;
for(int i = 0;iN/2)return;
if(right>N/2)return;
//根据剩余括号数量进行剪枝
if(left generateParenthesis(int n) {
myslove(0,"",2*n);
return res;
}
};
思路:以上思路都是对每个位置的括号情况进行枚举。既然左括号和右括号数是一定的,我们可不可以尝试对左右剩余括号的数量进行枚举呢?当左括号或者右括号都小于0时,得到的最终序列肯定不合法,当剩余的左括号大于右括号时,肯定也不合法。除了以上情况外,当左括号为0并且右括号为0时,得到的一定是合法序列。
class Solution {
private:
vector str;
void dfs(int left,int right,string temp){
//剩余左括号或者剩余右括号小于0,一定不合法。
if(left<0)return;
if(right<0)return;
//当剩余的左右括号都为0时,得到合法序列。
if(left==0&&right==0){
str.push_back(temp);
return;
}
//当剩余左括号大于剩余右括号时,一定不合法。
if(left>right){
return;
}
if(left>0){
dfs(left-1,right,temp+"(");
}
if(right>0){
dfs(left,right-1,temp+")");
}
}
public:
vector generateParenthesis(int n) {
int l = n;
int r = n;
dfs(l,r,"");
return str;
}
};
为什么当剩余左括号和剩余右括号的数量都为0时,得到的一定是合法的序列呢?这是因为当一个括号序列不合法时,一定从某个位置开始,导致了剩余的左括号数大于了剩余右括号数。所以当剩余的左括号数大于了剩余右括号数这种情况排除了后,并且左右括号数一定时,当剩余左括号和剩余右括号的数量都为0时,一定时合法的。



