【递归&动态规划】一个长度为n的无重复序列入栈的所有出栈方式

<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">例如<span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">3</span><span style="font-family: 宋体;">这三个数字,入栈并出栈共有</span><span style="font-family: Calibri;">5</span><span style="font-family: 宋体;">种方式,分别为:</span><span style="font-family: Calibri;">321</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">312</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">231</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">213</span><span style="font-family: 宋体;">、</span><span style="font-family: Calibri;">123</span><span style="font-family: 宋体;">。那么对于长度为</span><span style="font-family: Calibri;">n</span><span style="font-family: 宋体;">的无重复序列中所有的出栈方式有哪些呢?</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-size: 14px; line-height: 21px;"><span style="font-family:宋体;">本题属于动态规划问题与卡特兰数有关,后来看到一篇blog <a target=_blank href="http://blog.csdn.net/zqt520/article/details/8010485">http://blog.csdn.net/zqt520/article/details/8010485</a> 最后介绍了一种递归模拟法,觉得能够对递归有个更深的理解。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-size: 14px; line-height: 21px;"><span style="font-family:宋体;">
</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">用队列(queue)来模拟输入,队列的输出则按照原先序列的顺序。使用一个栈(stack)来模拟入栈和出栈,结果保存在另外一个队列(queue)。</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">现在的问题来了,怎么样可以实现所有的出栈入栈操作。首先来看看出栈和入栈是怎么回事,对于<span style="font-family: Calibri;">123</span><span style="font-family: 宋体;">这个序列,</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">先入栈之后有两种选择,</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">出栈和</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">入栈,而若</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">已经入栈之后,在</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">出栈之前</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">则不能先行出栈,故对于</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">我们只需要考虑其在</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">入栈之前出栈的情况,若</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">在栈内时</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">入栈,则</span><span style="font-family: Calibri;">1</span><span style="font-family: 宋体;">与</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">只能看成一个整体。</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">这样就可以用递归的方式求解,伪代码如下:</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">dostack(输入队列,中间栈,输出队列)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">if(输入队列为空)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">    if(中间栈为空)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">        输出输出队列中的结果</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">    else</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">中间栈出栈,放入输出队列</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">dostack(输入队列,中间栈,输出队列)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">else</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">    if(中间栈非空)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">        新建输入队列<span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">、中间栈</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">、输出队列</span><span style="font-family: Calibri;">2</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">        中间栈<span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">出栈并放入输出队列</span><span style="font-family: Calibri;">2</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">dostack(输入队列<span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">,中间栈</span><span style="font-family: Calibri;">2</span><span style="font-family: 宋体;">,输出队列</span><span style="font-family: Calibri;">2</span>)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">    输入队列出队一个数并压入中间栈</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">dostack(输入队列,中间栈,输出队列)</p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; color: rgb(69, 69, 69); font-family: 'Microsoft Yahei', 微软雅黑, Tahoma, Arial, Helvetica, STHeiti; font-size: 14px; line-height: 21px;">其基本思想为对于中间栈的每一个时刻拍照,都递归其后续的所有可能,由于在递归返回的时候还需要递归前的信息,所以每次递归都是新建数据结构而保存当前时刻的状态。若输入队列已经为空,则中间栈只有一种出栈方式,中间栈也为空时递归结束。</p>
#include <iostream> 
#include <string> 
using namespace std;
#include "queue"
#include "stack"


void printOut(queue <int> out){
	while(!out.empty()){
		cout<<out.front()<<"\t";
		out.pop();
	}
	cout<<endl;
}
void dostack(queue <int> in, stack <int> s,queue <int> out) {
	if(in.empty()){
		if(s.empty())
			printOut(out);
		else{
			
				out.push(s.top());
				s.pop();
				dostack(in, s, out);			
		}
	}
	else{
		if(!s.empty()){
			queue <int> tin=in;
			stack <int> ts=s;
			queue <int> tout=out;//引入ts、tout、tin是为了保存另一种状态
			tout.push(ts.top());
			ts.pop();
			dostack(tin, ts, tout);
		}
			s.push(in.front());
			in.pop();
			dostack(in, s, out);
	}
}

int main(){
	int m=0, n=3, count=0;
	queue <int> in;
	stack <int> s;
	queue <int> out;

	for(int i=n;i>=1;i--)  
	<span style="white-space:pre">	</span>in.push(i);  
	dostack(in,s,out);  	
	system("pause");
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值