"((()))", "(()())", "(())()", "()(())", "()()()"
题目意思是说,给出所有的合法的括号形式。比如,手动地来写写。
n=1时, "()"
n=2时,"()()", "(())"
n=3时,"((()))", "(()())", "(())()", "()(())", "()()()"
这个问题比较适合用递归来解决。经过一些探索,想到一个比较自然也比较好理解的办法。描述如下:
当n=1时,显然只能写出"()"
当n=2时,为什么写出了"()()", "(())",这和n=1时候的结果有什么关系呢?你可以看成有个基本元素element="()",它尝试把它本身放入上一次的结果中,也就是n=1的结果中。
当n=1时, 观察下面这个表达式
| ( | ) |
可以认为,对上面表达式中的三个竖线而言,每个竖线都是一个候选的插入位置。
如果把element="()" 插入竖线一,将构成()()
如果把element="()" 插入竖线二,将构成(())
如果把element="()" 插入竖线三,将构成()()
其中过滤掉重复,最后得到当n=2时,合法的括号形式为"()()", "(())"
把上面的思考写成code,如下
// // Solution.h // LeetCodeOJ_021_GeneratePairsOfParenthese // // Created by feliciafay on 12/18/13. // Copyright (c) 2013 feliciafay. All rights reserved. // #ifndef LeetCodeOJ_021_GeneratePairsOfParenthese_Solution_h #define LeetCodeOJ_021_GeneratePairsOfParenthese_Solution_h #include <vector> #include <iostream> #include <set> #include <string> #include <cmath> using namespace std; class Solution { public: vector<string> generateParenthesis(int n) { if(n<1){ vector<string> res_vec; return res_vec; } else if(n==1){ vector<string> res_vec; res_vec.push_back("()"); return res_vec; }else{ vector<string> pre_vec=generateParenthesis(n-1); set<string> filter_set; vector<string> res_vec; for(int i=0;i<pre_vec.size();i++){ string pre_str=pre_vec[i]; int pre_str_len=(int)pre_str.length(); for(int j=0;j<=pre_str_len;j++){ string now_str=pre_str.substr(0,j)+"()"+pre_str.substr(j,pre_str_len-j); if(filter_set.find(now_str)==filter_set.end()){ filter_set.insert(now_str); res_vec.push_back(now_str); } } string now_str=pre_str+"()"; if(filter_set.find(now_str)==filter_set.end()){ filter_set.insert(now_str); res_vec.push_back(now_str); } } return res_vec; } } }; #endif
小结
(1) 一开始思考进入误区,写了很久输出结果总是不全。后来换了角度看问题,终于正确了。
(2) 这个题目背后的奥秘是卡特兰数,这个目前还没有开始看,稍后更新。