问题链接
LeetCode 22. Generate Parentheses
题目解析
括号匹配问题:给出数字n,求n对括号所有可能的匹配形式。
解题思路
明显使用递归的方法求解,最初的想法是利用两个变量 (left)和 (right) 记录剩余可使用的左右括号数,当 (left>right) 时,不可能匹配,直接返回;当 (left=right=0) 时,代表匹配完毕;否则,根据 left 和 right 的剩余数量分别递归调用。
参考代码
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string ans = "";
DFS(n, n, ans, res);
return res;
}
void DFS(int left, int right, string ans, vector<string> &res) {
if(left > right) return;
if(left == 0 && right == 0)
res.push_back(ans);
else {
if(left > 0) DFS(left-1, right, ans+"(", res);
if(right > 0) DFS(left, right-1, ans+")", res);
}
}
};
改进
提交之后确实可以AC,但是发现需要4ms,只能打败40%左右的提交,说明不是很好,仔细想想发现是剪枝不够。如果 left=0,即左括号已经用尽,此时直接添加右括号即可,不需要再递归求解,这样可以减少不少的开销。
代码做了稍微的调整,left 和 right的值定义为已经使用的左右括号数。提交之后大约3ms,可打败95%以上的提交,足够了,参考代码如下:
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string ans = "";
DFS(n, 0, 0, ans, res);
return res;
}
void DFS(int n, int left, int right, string ans, vector<string> &res) {
if(left < right) return;
if(left == n) {
for(int i=0; i < left-right; i++)
ans = ans+")";
res.push_back(ans);
}
else {
if(left < n) DFS(n, left+1, right, ans+"(", res);
if(right < n) DFS(n, left, right+1, ans+")", res);
}
}
};
哦对了,上面这段代码还可以简短一点,效果是一样的,参考代码如下:
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
string ans = "";
DFS(n, 0, 0, ans, res);
return res;
}
void DFS(int n, int left, int right, string ans, vector<string> &res) {
if(left+right == 2*n) {
res.push_back(ans);
return;
}
if(left < n) DFS(n, left+1, right, ans+"(", res);
if(right < left) DFS(n, left, right+1, ans+")", res);
}
};
时间复杂度
这里的时间复杂度计算起来有些麻烦,参考官方题解:https://leetcode.com/problems/generate-parentheses/solution/。
LeetCode All in One题解汇总(持续更新中...)
本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.