文章目录
- 写在前面
- Tag
- 题目来源
- 解题思路
- 方法一:暴力法
- 方法二:回溯
- 写在最后
写在前面
本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……
专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:
- Tag:介绍本题牵涉到的知识点、数据结构;
- 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
- 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
- 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
- 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。
Tag
【字符串】【暴力枚举】【回溯】
题目来源
22. 括号生成
解题思路
方法一:暴力法
思路
利用递归计算出所有可能的括号组合,判断是否有效,有效的存入答案数组。实现过程直接见代码。
代码
class Solution {
private:
bool isValid(const string& str) {
int cnt = 0;
for (const char&c : str) {
if (c == '(') {
++cnt;
}
else {
--cnt;
}
if (cnt < 0) {
return false;
}
}
return cnt == 0;
}
void genenrate_all(string& cur, int n, vector<string>& res) {
// 递归出口:满足括号的长度要求,并且有效
if (n == cur.size()) {
if (isValid(cur)) {
res.push_back(cur);
}
return;
}
cur += '(';
genenrate_all(cur, n, res);
cur.pop_back();
cur += ')';
genenrate_all(cur, n, res);
cur.pop_back();
}
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string cur;
genenrate_all(cur, n * 2, res);
return res;
}
};
复杂度分析
时间复杂度: O ( n × 2 2 n ) O(n \times 2^{2n}) O(n×22n),选与不选问题有 2 2 n 2^{2n} 22n 个可能的括号,验证每一个括号是否有效需要花费 O ( n ) O(n) O(n) 的时间。
空间复杂度:
O
(
n
)
O(n)
O(n),除了答案数组之外,我们所需要的空间取决于递归栈的深度,每一层递归函数需要
O
(
1
)
O(1)
O(1) 的空间,最多递归 2n
层,因此空间复杂度为
O
(
n
)
O(n)
O(n)。
方法二:回溯
思路
方法一还有改进的地方,我们可以只在序列有效时才增加左括号或右括号:
- 当左括号的数量小于
n
时,我们可以放置一个左括号; - 当右括号的数量小于左括号的数量时,我们可以放置一个右括号。
代码
class Solution {
private:
void dfs(vector<string>&res, string cur, int n, int lc, int rc) {
if (rc > lc || lc > n || rc > n) {
return;
}
if (lc == rc && rc == n) {
res.push_back(cur);
return;
}
dfs(res, cur + '(', n, lc + 1, rc);
dfs(res, cur + ')', n , lc, rc + 1);
}
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
int lc = 0, rc = 0;
dfs(res, "", n, lc, rc);
return res;
}
};
复杂度分析
回溯方法的时间和空间复杂度这里不做分析,感兴趣的可以参考 官方题解.
写在最后
如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。
最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。