1-5入栈顺序有多少种可能出栈结果

方法一、

A.  1个元素入栈出栈一种可能记作f(1) = 1;

B.  2个元素入栈出栈有两种可能记f(2) = 2;

C. 3个元素入栈,考虑最后一个元素,出栈为第一个位置1种,第二个位置2种,第三个位置f(2)种,记作f(3) = 5;

D. 4个元素入栈,考虑最后一个元素,出栈为第一个位置1种,第二个位置(前面只有一个元素pop出去了,在3个push任意位置插入一个pop)有3种可能,第三个位置(说明已经pop出去两个元素,考虑1-3三个数,pop其中两个,若两个连续有前面f(2)种,不连续只有一种,即num_pop(1,2) = 2,num_pop(2,3)=2,num_pop(1,3)=1)有共5种可能,第四个位置pop即为前面f(3)的值,即f(4) = 1 + 3 + 5 + 5 = 14种。

E. 5个元素入栈,考虑最后一个元素,出栈为第一个位置1种,第二个位置(前面有4个元素选择一个pop)有4种可能,第三个位置(说明已有两个元素pop出去,若为pop的为1,2有2种,1,3有一种,1,4有1种,若pop的为2,3有2种,pop2,4有1种,pop3,4有2种)共计9种,第四个位置(说明已经pop出去三个元素,那么假设1未被pop,有f(3)种,2未被pop有f(2)种,3未被pop有f(2)种,4未被pop有f(3)种)共14种,第五个位置即f(4),因此f(5) = 1 + 4 + 9 + 14 + 14 = 42种。


方法二、

A.  f(4) = |push| x | x | x | x | x | x |pop|

B. f(5) = |push|pop| f(4) | + |push| push | x | x | x | x | x | x | x | pop |

显然 |push| push | x | x | x | x | x | x | x | pop | > f(4) ,由于对应于第一个x可以是pop,可以有pop多一个在前。

设为:|push|push| x1 | x2 | x3 | x4 | x5 | x6 | x7 |pop|
x1一个pop不能让其产生消除第一个push

x2x1同时为pop时候,后面还有6个数即f(3) = 5种

x3消除第一个push是不可能的,不用考虑

x4和x1,x2,x3中两个个组合pop可以消除第一个push(但x1,x2同为pop不考虑)即有C(3)(2) - 1 = 2 种可能,而右边有4个空缺,有f(2) = 2种,综合考虑有2*2 = 4 种。

x5消除第一个push是不可能的,不用考虑

x6消除第一个push,若x5为push,那么必然不成立。因此x1-x4排列2push,2pop,有C(4)(2) - 1 = 5种,而对于后者只有x7只有push一种可能,综合考虑有5*1 = 5种

x7消除第一个push,不可能。

因此,f(5) = f(4) + f(4) + 5 + 4 + 5 = 14 * 3 = 42


方法三、

卡特兰数 h(n)=h(n-1)*(4*n-2)/(n+1) = C(2n,n)/(n+1)  = c(2n,n)-c(2n,n+1) 将5代入 直接得到答案42

证明:

1. 假设1~n的元素,中第i个元素最后出栈,那么在i之前的元素都在i入栈前已经完成了出栈,即有f(i-1)种。所有i之后的元素在i入栈后,先后完成了入栈和出栈,有f(n-i)种。

令f(0) = 1,那么有; f(n) = f(0)*f(n-1) + f(1)*f(n-2)……f(n-1)*f(0) 

2. 用0,1分别表示出栈和入栈,那么1~5的入栈出栈操作可以用10位01bit位来模拟,但需要保证从左边到右边扫描过程中,1个个数总是大于或等于0的个数。

假设采用枚举的方法,即C(2n,n)种,有哪些不符合要求?

假设某个偶数位2m,产生了冲突,前面0的个数超出1个个数,显然2m位是0,那么必须有2m-1位刚好匹配完所有的push,即1,0对等。显然奇数不可能实现这个,一次不可能在偶数位冲突。

假设某个奇数位2m+1产生冲突,那么前2m位刚好匹配,2m+1位是0,然后后面有n-m-1个0,n-m个1,,将后面的数据都对应反向,即n-m个0,n-m-1个1,仍不影响该结果不可能是合理解,在n-m+m+1 = n+1个0,n-1个1产生的组合包含n个0,n个1产生的不合理解。

n-1个1,n+1个0,组合成2n个bit的列,在某一位上0的个数会超过1的个数,假设这个位是偶数位,显然不可能,若为奇数为,设为2*x + 1,将后面数据都反向对应有n-x-1个0,n-x个1,完全也不影响这个列成为不符合要求的列,即有n-1个1,n+1个0组合不合理情况包含n个0,n个1产生的不合理解。

即n-1个1,n+1个0,产生的不合理解即为全部不合理解。

因此h(n) = c(2n,n) - c(2n,n+1);


方法四、

代码解决:

少量数据可以直接10位bit,每次+1,判断是否有5个1,判断是否从左到右边遍历总是1个数不小于0个数,符合即可输出结果。

也可以初始化5个1,5个0,然后在这个集合中next_permutation,求所有集合,然后对每种组合进行判断,代码如下。

#include <iostream>
#include <algorithm>
#include <conio.h>
using namespace std;
int testify(int *a,int len)
{
	int num0 = 0;
	int num1 = 0;
	for(int i=0;i<len;++i)
	{
		if(a[i] == 1)
			++num1;
		else
			++num0;
		if(num0 > num1)
			return 0;		
	}
	return 1;
}
int main()
{
	int m[10] = {0,0,0,0,0,1,1,1,1,1};
	int count = 0;
	do{
		if(testify(m,10))
			++count;
	}while(next_permutation(m,m+10));
	cout<<"Total NO:"<<count<<endl;
	getch();
}
结果如下图所示:



  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值