Generate Parentheses

来源:互联网 发布:java代码换行符 编辑:程序博客网 时间:2024/06/06 12:44

Generate Parentheses

My Submissions
Total Accepted: 57885 Total Submissions: 176392 Difficulty: Medium

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个的所有括号数,按照左括号开始的数目进行枚举,后面插入需

要补充的括号数,代码,如下,但是忽略了一种情况

分析了下此方法较复杂,放弃。

class Solution {public:    vector<string> generateParenthesis(int n) {if(!n){ vector<string> ve; return ve;}        vector<string> * vectors = new vector<string> [n];for(int ve = 0; ve < n; ve ++){for( int l_num = ve + 1; l_num > 0; l_num --){string str_pre;for( int il_num = 0; il_num < l_num; il_num ++)str_pre.append("(");str_pre.append(")");int sub_num = ve + 1 - l_num;if( !sub_num) //有需要补充的子括号数{string str = str_pre;for( int ir_num = 0; ir_num < l_num -1; ir_num ++)str.append(")");vectors[ve].push_back(str);}else{//插在内部for( vector<string>::iterator ite = vectors[sub_num - 1].begin();ite != vectors[sub_num - 1].end(); ite ++){string str = str_pre;str.append(*ite);for( int ir_num = 0; ir_num < l_num -1; ir_num ++)str.append(")");vectors[ve].push_back(str);}//插在外部for( int wair_num = 1;wair_num <= l_num - 1; wair_num ++ ){for( vector<string>::iterator ite = vectors[sub_num - 1].begin();ite != vectors[sub_num - 1].end(); ite ++){string str = str_pre;for( int ir_num = 0; ir_num < wair_num; ir_num ++)str.append(")");str.append(*ite);for( int ir_num = 0; ir_num < l_num-1-wair_num; ir_num ++)str.append(")");vectors[ve].push_back(str);}}}}}//释放多余内存for(int i = 0; i < n-1; i++)vectors[i].clear();return vectors[n-1];    }};
二.网上看了某人的算法,所谓的卡特兰数,代码非常简单,就是建一个二叉树,然后深度搜索,要求每次分支,已经画的左括号数必须大于

右括号数,都画完时返回,代码如下:

class Solution {public:    vector<string> generateParenthesis(int n) {vector<string> re;if(!n)return re;string str = "";        generate(re,n,n,str);return re;    }void generate(vector<string> &re,int left,int right,string str){if( left == 0 && right == 0)re.push_back(str);if( left > 0)generate( re, left - 1, right, str +"(");if( right > left && right > 0)generate( re, left, right - 1, str + ")");return;}};
三. 卡特兰数应用例子:(引用网上例子

入栈出栈顺序问题:给定一个长度为n的不重复数组,求所有可能的入栈出栈顺序。该问题解的个数也是卡特兰数,根据上面的思路,我们也

可以写出一个类似的代码:

[cpp] view plaincopyprint?
  1. void inoutstack(int in,int out,deque<int> &q,stack<int> &s,deque<int> seq,vector<deque<int>> &result)  
  2.     {  
  3.         if(!in&&!out)  
  4.         {  
  5.             result.push_back(q);  
  6.             return;  
  7.         }  
  8.   
  9.         if(in>0)  
  10.         {  
  11.             s.push(seq.front());  
  12.             seq.pop_front();  
  13.             inoutstack(in-1,out,q,s,seq,result);  
  14.             seq.push_front(s.top());  
  15.             s.pop();  
  16.         }  
  17.   
  18.         if(out>0&&in<out)  
  19.         {  
  20.             q.push_back(s.top());  
  21.             s.pop();  
  22.             inoutstack(in,out-1,q,s,seq,result);  
  23.             s.push(q.back());  
  24.             q.pop_back();  
  25.         }  
  26.     }  
上述代码由于采用了栈和队列模仿整个过程,所以显得略微复杂,但是代码的基本结构还是符合一个类似的基本规则:在某一个特定时刻,入
栈的次数大于或者等于出栈的次数。在生成括号的问题中,我们利用一个string来保存结果,由于打印左括号时不影响打印右括号,所以无需复
杂的状态恢复。在入栈出栈顺序问题中,由于两次递归调用共享同一个栈和队列,所以我们需要手动恢复其内容。在恢复时,队列会从头部删
除和添加,所以我们采用了deque,它可以在头部添加和删除元素。queue只能在头部删除元素,所以没有采用。
中文:卡特兰数
  Catalan数是组合数学中一个常出现在各种计数问题中出现的数列。由以比利时的数学家欧仁·查理·
卡塔兰 (18141894)命名。
  原理:
  令h(
0)=1,h(1)=1,catalan数满足递归式:
  h(n)
= h(0)*h(n-1+ h(1)*h(n-2+  + h(n-1)h(0) (其中n>=2)
  该递推关系的解为:
  h(n)
=C(2n,n)/(n + 1) (n=1,2,3,)
       另类递归式:  h(n)=((4*n-2)/(n+1))*h(n-1);
  
  前几项为 (OEIS中的数列A000108): 
112514421324291430486216796
58786208012742900
267444096948453535767012964479047763870017672631906564120420
244662670209148256364034305961365012899041473244861946401452
应用

  我总结了一下,最典型的四类应用:(实质上却都一样,无非是递归等式的应用,就看你能不能
分解问题写出递归式了)
1.括号化问题。

  矩阵链乘: P
=a1×a2×a3×……×an,依据乘法结合律,不改变其顺序,只用括号表示成对的
乘积,试问有几种括号化的方案?(h(n)种)
2.出栈次序问题。

  一个栈(无穷大)的进栈序列为1,
2,3,..n,有多少个不同的出栈序列?
  类似:
  (
1)有2n个人排成一行进入剧场。入场费5元。其中只有n个人有一张5元钞票,另外n人只有
10元钞票,剧院无其它钞票,问有多少中方法使得只要有10元的人买票,售票处就有5元的钞票
找零?(将持5元者到达视作将5元入栈,持10元者到达视作使栈中某5元出栈)
  (
2)在圆上选择2n个点,将这些点成对连接起来,使得所得到的n条线段不相交的方法数。
3.将多边行划分为三角形问题。

  将一个凸多边形区域分成三角形区域的方法数
?
  类似:一位大城市的律师在她住所以北n个街区和以东n个街区处工作。每天她走2n个街区去上班
。如果她
  从不穿越(但可以碰到)从家到办公室的对角线,那么有多少条可能的道路?
  类似:在圆上选择2n个点,将这些点成对连接起来使得所得到的n条线段不相交的方法数
?
4.给顶节点组成二叉树的问题。

  给定N个节点,能构成多少种形状不同的二叉树?
  (一定是二叉树
!
  先去一个点作为顶点,然后左边依次可以取0至N
-1个相对应的,右边是N-1到0个,两两配对相乘,
就是h(0)*h(n-1+ h(2)*h(n-2+  + h(n-1)h(0)=h(n))
  (能构成h(N)个)

0 0
原创粉丝点击