算法小白,最近刷LeetCode。希望能够结合自己的思考和别人优秀的代码,对题目和解法进行更加清晰详细的解释,供大家参考^_^
22. Generate Parentheses
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
For example, given n = 3, a solution set is:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
题目要求输出满足匹配关系的n对括号的所有可能情况,一方面考虑到括号匹配判断使用栈作为基础的数据结构,对应的,构造这样的序列应该可以用递归进行;另一方面,该题和17题Letter Combinations of a Phone Number十分相似,因此,首先想到的解法就是递归,实际测试也是可行的:
由于递归要一步步构造最终的序列,每一步都要根据当前序列的情况判断下一次应该加入左括号还是右括号。观察发现,当已有序列中左右括号数目相等时,下一步只能添加左括号;左括号数目大于右括号数目时,下一步既可以添加左括号,又可以添加右括号,只要保证左和右括号数目都不大于n就行;右括号数目大于左括号数目的情况显然是错误的,递归时要抛弃掉。
class Solution {
public:
// 递归函数,str为每种可能的序列,每递归一次,根据当前情况增加一个左括号或右括号
// lnum 和 rnum 分别表示当前序列中左括号和右括号的数目
// n 声明为常量,即给定的参数;vi为结果集
void fun(string str, int lnum, int rnum, const int n, vector<string> &vi){
// 如果左右括号数目相等且都为n,即找到了一种可能的序列组号,加入结果集中,返回
if (lnum == n && rnum == n) {
vi.push_back(str);
return ;
}
// 左右括号数目相等,只能添加左括号。这也保证了不可能出现rnum > lnum的情况
if (lnum == rnum) {
fun(str + '(', lnum + 1, rnum, n, vi);
} else { // 左右括号数目不等,其实等价于 lnum > rnum
// 只要数目不超过n,就可以往后添加左括号会右括号,对应的lnum或rnum加1
if (lnum < n) fun(str + '(', lnum + 1, rnum, n, vi);
if (rnum < n) fun(str + ')', lnum, rnum + 1, n, vi);
}
}
vector<string> generateParenthesis(int n) {
vector<string> vi;
// 调用递归函数,初始值为空序列,左右括号数目都为0
fun(string(""), 0, 0, n, vi);
return vi;
}
};
同17题一样,这题也有非递归的构造方法,这里暂不赘述。