📋 前言
二十多年前,我在不足二十平米的外婆家小院里蹦跶,感觉世界美好,我早已走遍。
——赵挺《外婆》
以下是正文
🍅 题目
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]
示例 2:
输入:n = 1
输出:["()"]
提示:
- 1 <= n <= 8(重点!!!)
🍅 解题思路
🍏 方法一:回溯法穷举所有结果
解决这个问题首先要明确两点:
- 1、一个符合条件的括号组合左括号数目等于右括号数量,则最后结果中括号总个数为2n
- 2、在有效括号组合的前k位,对任意0<=k<=2n,都满足左括号数量大于等于右括号数量。
然后就可以套用回溯算法的框架,穷举出所有结果。
在本题中:结束条件为路径长度达到2n
路径为左右括号的排列
穷举算法框架:
result = [];
void backtrace(路径,选择列表) {
if(满足结束条件) {
result.push_back(路径);
return;
}
for(选择:选择列表) {
做选择
backtrace(路径,选择列表);
撤销选择
}
}
在穷举出所有可能之后,我们需要剔除所有不满足条件的括号组合,做一些剪枝,只返回满足条件的括号组合。
🍅 我的答案
class Solution {
public:
// s为路径,即生成有效括号过程中的字符串,result存储所有符合条件的括号组合字符串
// i为当前路径中已经有的左括号数量,j为当前路径中已经有的右括号数量
void drawParenthesis(int i,int j,int n,string &s,vector<string> &result) {
// 路径长度达到2n,已生成有效括号
if(s.size() == 2*n) {
result.push_back(s);
return;
}
// 左括号与右括号至多都为n
if(i>n) {
return;
}
// 在生成有效括号排列的过程中,左括号的数量始终大于等于右括号数量,否则就不能生成有效括号排列
if(j > i){
return;
} else {
// 左括号数量小于n的时候,即可以生成左括号也可以生成右括号,但左括号数量等于n的时候,只能生成右括号
if(i<n) {
// 选择生成左括号
s.push_back('(');
drawParenthesis(i+1,j,n,s,result);
// 撤销选择
s.pop_back();
}
// 选择生成右括号
s.push_back(')');
drawParenthesis(i,j+1,n,s,result);
// 撤销选择
s.pop_back();
}
}
vector<string> generateParenthesis(int n) {
string s = "";
vector<string> result;
// 初始状态为0个左括号,0个右括号
drawParenthesis(0,0,n,s,result);
return result;
}
};
🍅 优质解答
class Solution {
public:
vector<string> res;
void solve(int l, int r, int n, string cur) {
if (l == n && r == n) {
res.push_back(cur);
return;
}
if (l < n)
solve(l + 1, r, n, cur + "(");
if (r < l)
solve(l, r + 1, n, cur + ")");
}
vector<string> generateParenthesis(int n) {
if (n == 0)
return res;
solve(0, 0, n, "");
return res;
}
};
🍅 知识积累
- 1、string也有push_back()方法和pop_back()方法,push_back()向字符串末尾添加一个字符,pop_back()为删除字符串末尾一个字符
🍅 题外话——论如何使用这一题的解答让电脑崩掉
题目给出的括号对数是1-8,在本地调试生成括号这道题时,突然想看看生成多一点的括号需要执行多长时间,随便输入了个23,结果杯具了,电脑直接卡死,一道小小的算法题就能轻易干崩电脑,以后写循环要注意一点,太可怕了!
随手点赞👍一次,运气增加一分哦🙏🙏🙏
注:本文中题目信息及优质解答来自力扣网