[LeetCode] Generate Parentheses 解题报告
2017-03-13 20:26
357 查看
[题目]
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对括号,写一个函数生成所有合法的组合。
例如,给定n = 3,解集是:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
[解题思路]
有两种想法,一种是先枚举出用’(‘或’)’构成长度为2n的字符串的所有可能,一共有22n,然后对于每一种可能,去判断一下是否合法,然后获得所有合法的可能。另一种自然的想法是使用递归,我采用的是递归的解法。
关于什么是递归,为什么会想到使用递归,这里就不细讲了。因为递归这种思想,对初学者而言有点难,对已经入门的却又很自然。建议初学者单步调试一下递归的代码,具体看一下执行过程中那些变量是什么样的,这样或许容易理解递归究竟是怎么递归下去的,又是怎么回溯上来的。
我这里设计的递归函数如下:
res是最后的结果,作为引用传入,也可以设成一个全局变量。
leftQuote是当前字符串s中已有的左括号个数。
rightQuote是当前字符串s中已有的右括号个数。
n是题目中输入的n,也可以改成全局变量。
s是当前递归到的字符串。
递归其实就是有条理地在进行状态搜索。
先判断一下当前的字符串s是否是一个合法的括号组合。
如果当前s中leftQuote=rightQuote=n,那么说明当前的s已经是一个合法的括号组合,可以将它加入res。而且在s的基础上再继续添加任何字符都不可能构成其他的合法字符,所以不需要继续递归下去。这是递归的终结点。
如果s还不是一个合法的括号组合,那么可以在s的基础上扩展一个’(‘或’)’。
只要leftQuote<n,就可以扩展一个’(‘,以s+’(‘为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。
如果leftQuote>rightQuote,就可以扩展一个’)’,以s+’)’为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。
这样的一个递归,不会有漏掉没有搜索的状态,因为它保证了所有可能构成合法括号组合的前缀s都会被搜索到。同时,它又不会永无止境地递归下去,因为leftQuote<n和leftQuote>rightQuote两个继续递归的条件保证了最终一定会达到leftQuote=rightQuote=n,而这是一个终结状态。
补充一点,这里实际上(leftQuote, rightQuote, s)构成了递归的状态,s控制了结果,leftQuote和rightQuote控制了递归的方向和递归的停止。实际上,用这三个变量来表示状态,是有多余的,只是为了便于理解。
[C++代码]
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对括号,写一个函数生成所有合法的组合。
例如,给定n = 3,解集是:
[
“((()))”,
“(()())”,
“(())()”,
“()(())”,
“()()()”
]
[解题思路]
有两种想法,一种是先枚举出用’(‘或’)’构成长度为2n的字符串的所有可能,一共有22n,然后对于每一种可能,去判断一下是否合法,然后获得所有合法的可能。另一种自然的想法是使用递归,我采用的是递归的解法。
关于什么是递归,为什么会想到使用递归,这里就不细讲了。因为递归这种思想,对初学者而言有点难,对已经入门的却又很自然。建议初学者单步调试一下递归的代码,具体看一下执行过程中那些变量是什么样的,这样或许容易理解递归究竟是怎么递归下去的,又是怎么回溯上来的。
我这里设计的递归函数如下:
void generateParenthesisRecursively(vector<string>& res, int leftQuote, int rightQuote, int n, string s);
res是最后的结果,作为引用传入,也可以设成一个全局变量。
leftQuote是当前字符串s中已有的左括号个数。
rightQuote是当前字符串s中已有的右括号个数。
n是题目中输入的n,也可以改成全局变量。
s是当前递归到的字符串。
递归其实就是有条理地在进行状态搜索。
先判断一下当前的字符串s是否是一个合法的括号组合。
如果当前s中leftQuote=rightQuote=n,那么说明当前的s已经是一个合法的括号组合,可以将它加入res。而且在s的基础上再继续添加任何字符都不可能构成其他的合法字符,所以不需要继续递归下去。这是递归的终结点。
if (leftQuote == rightQuote && leftQuote == n) { res.push_back(s); return; }
如果s还不是一个合法的括号组合,那么可以在s的基础上扩展一个’(‘或’)’。
只要leftQuote<n,就可以扩展一个’(‘,以s+’(‘为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。
if (leftQuote < n) generateParenthesisRecursively(res, leftQuote + 1, rightQuote, n, s + "("); }
如果leftQuote>rightQuote,就可以扩展一个’)’,以s+’)’为前缀的字符串可能成为一个合法括号匹配,因此需要继续递归。
if (leftQuote > rightQuote) generateParenthesisRecursively(res, leftQuote, rightQuote + 1, n, s + ")");
这样的一个递归,不会有漏掉没有搜索的状态,因为它保证了所有可能构成合法括号组合的前缀s都会被搜索到。同时,它又不会永无止境地递归下去,因为leftQuote<n和leftQuote>rightQuote两个继续递归的条件保证了最终一定会达到leftQuote=rightQuote=n,而这是一个终结状态。
补充一点,这里实际上(leftQuote, rightQuote, s)构成了递归的状态,s控制了结果,leftQuote和rightQuote控制了递归的方向和递归的停止。实际上,用这三个变量来表示状态,是有多余的,只是为了便于理解。
[C++代码]
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> result;
generateParenthesisRecursively(result, 0, 0, n, "");
return result;
}
void generateParenthesisRecursively(vector<string>& res, int leftQuote, int rightQuote, int n, string s) {
if (leftQuote == rightQuote && leftQuote == n) { res.push_back(s); return; }
if (leftQuote < n)
generateParenthesisRecursively(res, leftQuote + 1, rightQuote, n, s + "(");
if (leftQuote > rightQuote) generateParenthesisRecursively(res, leftQuote, rightQuote + 1, n, s + ")");
}
};
相关文章推荐
- 【LeetCode】Generate Parentheses 解题报告
- 【LeetCode】Generate Parentheses 解题报告
- LeetCode解题报告—— 4Sum & Remove Nth Node From End of List & Generate Parentheses
- [LeetCode] Generate Parentheses 解题报告
- [LeetCode]Generate Parentheses, 解题报告
- [LeetCode] Generate Parentheses 解题报告
- 【LeetCode】20.Valid Parentheses解题报告
- leetcode解题报告20. Valid Parentheses
- [Leetcode] 20. Valid Parentheses 解题报告
- Leetcode #22 Generate Parentheses 创建括号 解题报告
- 【LeetCode】Longest Valid Parentheses 解题报告
- LeetCode: Longest Valid Parentheses 解题报告
- [leetcode] 241. Different Ways to Add Parentheses 解题报告
- [leetcode] 20. Valid Parentheses 解题报告
- [LeetCode] Valid Parentheses 解题报告
- 【LeetCode】Valid Parentheses 解题报告
- LeetCode解题报告--Valid Parentheses
- [leetcode] 32. Longest Valid Parentheses 解题报告
- LeetCode解题报告—— Longest Valid Parentheses
- [LeetCode] Longest Valid Parentheses 解题报告