22. Generate Parentheses
来源:互联网 发布:整形医院网络咨询收入 编辑:程序博客网 时间:2024/05/21 10:25
基本素养,只要见到求所有可能组合的情况(所有可能组合的个数), 首先立马想几个概念词:DFS、递归、回溯。有了这个直觉,你就省去了大量的时间,直接往递归上去套。接下来就是考虑怎么设计递归函数的问题了,速度自然会快很多。
这道题的要求是给定n对括号,生成所有正确的括号组合。这道题要生成正确形式的括号匹配的数量,其实就是卡特兰数。
卡特兰数,一种有着特殊规律的数列,先用一道题来引出卡特兰数。
10个高矮不同的人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问有多少种排列方式?
我们可以先把这10个人从低到高排列,然后,选择5个人排在第一排,那么剩下的5个人肯定是在第二排。
用0表示对应的人在第一排,用1表示对应的人在第二排,那么含有5个0,5个1的序列,就对应一种方案。
比如0000011111就对应着
第一排:0 1 2 3 4
第二排:5 6 7 8 9
0101010101就对应着
第一排:0 2 4 6 8
第二排:1 3 5 7 9
所以,看到问题相应的转换为,这样的满足条件的01序列有多少个。
观察规律我们发现1的出现前边必须有一个相应的0对应,所以从左到右的所有序列中0的个数要一直大于1的个数。那这种数列有多少种排列方式呢?
那么我们从左往右扫描,第一次出现1的个数等于0的个数是第k位,那么在此之前,0的个数是大于1的个数的。在此之后,0的个数也是大于1的个数的。所以第k位0和1的个数第一次相等的排列有他们这两部分的个数相称的结果。那么所有的k有多少种,则把它们相加起来,就是最后的排列数。这是一个递归的问题。
即 a(n)=a(0)×a(n-1)+a(1)*a(n-2)+…+a(n-1)*a(0)
C语言版
#include<stdio.h>#include<stdlib.h>#include<string.h>void generater(char **result,char *temp,int n,int *returnSize,int left,int right){ if(right==n) { temp[left+right]='\0'; strcpy(result[(*returnSize)++],temp); return; } if(left<n) { temp[left+right]='('; generater(result,temp,n,returnSize,left+1,right); } if(right<left) { temp[right+left]=')'; generater(result,temp,n,returnSize,left,right+1); }}char** generateParenthesis(int n, int* returnSize) { int i; char **result,*tmp; tmp=malloc(sizeof(char)*(2*n+1)); result=malloc(sizeof(char*)*10000); for(i=0;i<10000;i++) result[i]=(char *)malloc(sizeof(char)*(2*n+1)); if(n>0) generater(result,tmp,n,returnSize,0,0); return result;}int main(){ int n,size=0,i; char **result; scanf("%d",&n); result=(char **)malloc(sizeof(char*)*1000); for(i=0;i<10000;i++) result[i]=(char *)malloc(sizeof(char)*(2*n+1)); result=generateParenthesis(n, &size); for(i=0;i<size;i++) printf("%s\n",result[i]); return 0;}
用二叉树形象的表示这种关系。然后再把二叉树转化为代码的形式。因为二叉树的定义就是递归定义的,因此本题很明显应该使用递归的形式。
从上面的图片中我们可以很明显的看到,最后五条画黑线的就是最终的结果,其中左分支都是添加左括号,又分支都是添加右括号。
那么我们在什么情况下添加左括号呢?很明显,最多能添加n个左括号,在递归调用的时候,在能传递到最底层的共用字符串中先添加”(“,然后left+1,递归调用就可以。
那什么时候添加右括号呢?当左括号个数大于右括号的个数时添加右括号。
C++版本
#include<iostream>#include<string>#include<vector>using namespace std;class Solution {public: vector<string> generateParenthesis(int n) { vector<string> result; string s; if(n>0) generatehelper(result,s,n,0,0); return result; } void generatehelper(vector<string> &result,string &s,int n,int left,int right) { if(right==n) { result.push_back(s); } else { if(left<n) { s+="("; generatehelper(result,s,n,left+1,right); s.resize(s.size()-1);// s.erase(s.size()-1);该句话是为了实现回溯,考虑一下每次执行该句时上一句的递归一定已经实现了,所以需要去除最后一个括号 } if(right<left) { s=s+")"; generatehelper(result,s,n,left,right+1); s.resize(s.size()-1); } } }};/*class Solution {public: vector<string> result; vector<string> generateParenthesis(int n) { generate(0, 0, "", n); return result; } void generate(int left, int right, string s, int n) { if(right == n) { result.push_back(s); } else { if(left < n) { generate(left + 1, right, s + "(", n); } if(right < left) { generate(left, right + 1, s + ")", n); } } }};*/void main(){ Solution solve; int N,i; vector<string> s; cin>>N; s=solve.generateParenthesis(N); for(i=0;i<s.size();i++) cout<<s[i]<<endl;}
第二种回溯法程序:
class Solution {public: vector<string> result; vector<string> generateParenthesis(int n) { generate(0, 0, "", n); return result; } void generate(int left, int right, string s, int n) { if(right == n) { result.push_back(s); } else { if(left < n) { generate(left + 1, right, s + "(", n); } if(right < left) { generate(left, right + 1, s + ")", n); } } }};
- [LeetCode]22.Generate Parentheses
- LeetCode --- 22. Generate Parentheses
- LeetCode 22.Generate Parentheses
- [Leetcode] 22. Generate Parentheses
- 【LeetCode】22.Generate Parentheses
- 22. Generate Parentheses
- [leetcode] 22.Generate Parentheses
- 【leetcode】22. Generate Parentheses
- Leetcode-22.Generate Parentheses
- [leetcode] 22. Generate Parentheses
- 22. Generate Parentheses
- 22. Generate Parentheses
- 22. Generate Parentheses LeetCode
- 22. Generate Parentheses
- leetcode 22. Generate Parentheses
- 22. Generate Parentheses
- [LeetCode]22. Generate Parentheses
- 22. Generate Parentheses
- Java关键字之abstract(抽象类的概念和使用)
- 悬浮术小研究
- 47. Spring Boot发送邮件
- 数据库事务并发带来的问题
- 未来要写的博客列表
- 22. Generate Parentheses
- 数据库的细节问题
- 图像匹配之序贯相似性(SSAD)——opencv
- java中的Exception和Error的区别
- onvif接口详解
- AscII与Unicode编码
- 【LightOJ 1136】
- HDU 5781 ATM Mechine(dp)
- Ubuntu12.04 安装及配置samba服务