两个问题:n对括号有多少种匹配方式与与最长递减子序列
2013-10-14 15:39
357 查看
一.n对括号有多少种匹配方式
首先想到的思路就是列出所有可能并对符合条件的进行计数。考虑采用回溯法,即将括号列表看做是字符串,对于字符串i位来说:要么是左括号→ 递归到i+1位;要么是右括号,递归到i+1位。之后所有位都列好后进行判断,是否符合条件。在统计过程中如果某个步骤右括号的数目大于左边括号的数目,或者统计完成后左右括号数目不等,则不符合条件。代码如下。
测试结果:2,2
二.求数组的最长递减子序列。例如{9,4,3,2,5,4,3,2}最长序列为{9,5,4,3,2}
这道题有两种解法。先看看编程之美提到中的动态规划解法(但对应的题目是求递增序列,其实都是类似的解法)。
比如已经知道5之前的递减序列为9,4,3,2。而5只会和2进行对比来判定是否可以加入递减序列,得到结论:一.9,4,3,2只是之前状态的总结;二.未来的状态只能通过现在状态来影响。所以采用动态规划解法。设定数组Lis[i]表示以a[i]为结尾的最大递减子序列的长度,则Lis[i+1]有两种情况:若a[i+1}大于所有的a[k](k>=0&&k<i+1),则Lis[i+1]为一,否则,若a[i+1]<a[k]且Lis[i+1]<Lis[k]+1,将a[i+1]加入最长递减子序列并更新Lis[i+1]。
最长递减序列的输出:可以在过程中求得最长递减子序列的最后一个数,然后向前递归,满足a[i+1]<a[k]且Lis[i+1]<Lis[k]+1则肯定在最长递减子序列中。代码如下:
测试结果为9,5,4,3,2
另外一种解法也是用Lis[i]数组表示以a[i]结尾的最长递减子序列,不同的是用二分查找来寻找每个a[i]的插入位置来更新List[i],这样在最后输出时直接通过List[i]来得到最长递减子序列(不知道大牛想出这样的算法出于何种考虑)。代码如下:
测试结果为:9,5,4,3,2
首先想到的思路就是列出所有可能并对符合条件的进行计数。考虑采用回溯法,即将括号列表看做是字符串,对于字符串i位来说:要么是左括号→ 递归到i+1位;要么是右括号,递归到i+1位。之后所有位都列好后进行判断,是否符合条件。在统计过程中如果某个步骤右括号的数目大于左边括号的数目,或者统计完成后左右括号数目不等,则不符合条件。代码如下。
#include <iostream> using namespace std; //微软44题 bool judgeparent(char a[],int n){ int leftnum=0,rightnum=0; for(int i=0;i<2*n;i++){ if(a[i] == 'l'){ ++leftnum; } else if(a[i]== 'r'){ ++rightnum; } if(rightnum > leftnum) return false; } if(leftnum==n && rightnum==n){ return true; } else return false; } void calsum(int current,int n,char a[],int &cnt){ if(current == 2*n){ if(judgeparent(a,n)){ ++cnt; } return; } a[current] = 'l'; calsum(current+1,n,a,cnt); a[current] = 'r'; calsum(current+1,n,a,cnt); } int main(){ int n,cnt =0; cout<<"please input num of parent:"<<endl; cin>>n; char *a = (char *)malloc(2*n); memset(a,0,2*n); calsum(0,n,a,cnt); cout<<cnt<<endl; system("PAUSE"); return 1; }
测试结果:2,2
二.求数组的最长递减子序列。例如{9,4,3,2,5,4,3,2}最长序列为{9,5,4,3,2}
这道题有两种解法。先看看编程之美提到中的动态规划解法(但对应的题目是求递增序列,其实都是类似的解法)。
比如已经知道5之前的递减序列为9,4,3,2。而5只会和2进行对比来判定是否可以加入递减序列,得到结论:一.9,4,3,2只是之前状态的总结;二.未来的状态只能通过现在状态来影响。所以采用动态规划解法。设定数组Lis[i]表示以a[i]为结尾的最大递减子序列的长度,则Lis[i+1]有两种情况:若a[i+1}大于所有的a[k](k>=0&&k<i+1),则Lis[i+1]为一,否则,若a[i+1]<a[k]且Lis[i+1]<Lis[k]+1,将a[i+1]加入最长递减子序列并更新Lis[i+1]。
最长递减序列的输出:可以在过程中求得最长递减子序列的最后一个数,然后向前递归,满足a[i+1]<a[k]且Lis[i+1]<Lis[k]+1则肯定在最长递减子序列中。代码如下:
#include <iostream> using namespace std; void PrintArray(int a[],int Lis[],int pos){ for(int i =pos-1;i>=0;i--){ if( (Lis[pos] = Lis[i]+1) && a[pos]<a[i]){ PrintArray(a,Lis,i); break; } } cout<<a[pos]<<" "; } void FindMaxDecrease(int a[],int n){ int *Lis = (int *)malloc(sizeof(int)*n); int maxlen = 1; int pos = 0; for(int i =0;i<n;i++){ Lis[i] =1; for(int j=0;j<i;j++){ if(a[i]<a[j] && (Lis[i]<Lis[j]+1)){ Lis[i] = Lis[j]+1; if(Lis[i]>Lis[pos]) pos = i; } } } PrintArray(a,Lis,pos); free(Lis); } int main(){ int a[] = {9,4,3,2,5,4,3,2}; FindMaxDecrease(a,8); system("PAUSE"); return 1; }
测试结果为9,5,4,3,2
另外一种解法也是用Lis[i]数组表示以a[i]结尾的最长递减子序列,不同的是用二分查找来寻找每个a[i]的插入位置来更新List[i],这样在最后输出时直接通过List[i]来得到最长递减子序列(不知道大牛想出这样的算法出于何种考虑)。代码如下:
#include <iostream> using namespace std; int BinarySearch(int a[],int key,int n){ int begin = 0; int end = n-1; while(begin <= end){ int mid = (begin+end)>>1; if(key > a[mid]) end = mid-1; else if(key < a[mid]) begin = mid+1; else return mid; } return begin; } void FindMaxDecrease(int a[],int n){ int *Lis = (int *)malloc(sizeof(int)*n); int *temp =(int *)malloc(sizeof(int)*n); temp[0] =a[0]; Lis[0] =1; int templen = 1; for(int i =1;i<n;i++){ int pos = BinarySearch(temp,a[i],templen); temp[pos] = a[i]; Lis[i] = pos+1; if(pos >= templen) templen++; } int maxlen = templen; for(int i = n-1;i>=0;i--){ if(templen == Lis[i]){ temp[templen-1] = a[i]; templen--; } } for(int i=0;i<maxlen;i++){ cout<<temp[i]<<" "<<endl; } free(temp); free(Lis); } int main(){ int a[] = {9,4,3,2,5,4,3,2}; FindMaxDecrease(a,8); system("PAUSE"); return 1; }
测试结果为:9,5,4,3,2
相关文章推荐
- 46.搜狐:四对括号可以有多少种匹配排列方式
- 四对括号可以有多少种匹配排列方式
- 最长括号匹配问题
- 四则运算问题扩充:1、题目避免重复;2、可定制(数量/打印方式);3、可以控制下列参数: 是否有乘除法、是否有括号、 数值范围、加减有无负数、除法有无余数、否支持分数 (真分数, 假分数, …)、是否支持小数 (精确到多少位)、打印中每行的间隔可调整;
- 【微软谷歌面试100题--【46】N对括号可以有多少种匹配排列方式
- 四对括号可以有多少种匹配排列方式?
- 最长括号匹配问题
- n对括号有多少种匹配排列方式
- 算法习题46:四对括号可以有多少种匹配排列方式?比如两对括号可以有两种:()()和(())
- 【编程题目】四对括号可以有多少种匹配排列方式?比如两对括号可以有两种:()()和(())
- [C++]连续最长括号匹配问题
- N对括号可以有多少种匹配排列方式
- [C++]连续最长括号匹配问题
- 最长的含有相同数目的01子串 & 括号匹配问题
- 四对括号可以有多少种匹配排列方式-新解法
- 四对括号可以有多少种匹配排列方式?比如两对括号可以有两种:()()和(())
- 46 四对括号可以有多少种匹配排列方式
- 四对括号可以有多少种匹配排列方式?比如两对括号可以有两种:()()和(())
- [C++]连续最长括号匹配问题解决策略二(学习)
- n对括号可以有多少种匹配排列方式(算法面试题)