给出一个堆栈的输入序列,试判断一个序列是否能够由这个堆栈输出。(HW.3.2)

本文介绍了如何判断一个序列是否能由给定的堆栈输出,详细解析了两种解决思路,包括抽象序列规律和模拟输入输出过程,并通过样例解释了算法的正确性和有效性。
摘要由CSDN通过智能技术生成

1.问题描述

【问题描述】给出一个堆栈的输入序列,试判断一个序列是否能够由这个堆栈输出。如果能,则为有效输出,返回总的出栈次数,如果不能,则为无效输出,返回0。序列的输入及输出都是从左往右。

1、输入输出序列皆为正整数,可能有重复的数字

2、如果一个数字在输入序列中没有出现,但在输出序列中出现,则为无效输出。

3、如果一个数字在输入序列中出现,但在输出序列中没有出现,只要输出可以通过对输入数字进行出栈操作获取,仍然为有效输出。(重要伏笔)

【输入形式】第一行包含两个数字:输入序列的长度与输出序列的长度;第二行为输入序列的数字;第三行为输出序列的数字。输入数据以空格隔开。

【输出形式】如果是一个有效的出栈序列,则返回总的出栈次数, 否则返回0
【样例输入1】

5 5

1 2 3 4 5

4 5 3 2 1

【样例输出】5
【样例说明】

可以按以下顺序执行:

push(1), push(2), push(3), push(4), pop() -> 4, push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

通过5次pop操作可以得到输出序列,因此返回5

【样例输入2】

5 5

1 2 3 4 5

4 3 5 1 2

【样例输出】0
【样例说明】

1不能在2之前输出,因此返回0

【评分标准】10个测试用例,每个10分

2.解决思路

首先我尝试的思路是抽象出可输出序列的规律。

思路一

分析问题

首先来考察以下不能输出的序列示例:
输入:1 2 3 4 5
输出:1 2 5 3 4
为什么这个示例不能输出呢?显然重点在于数字5的位置
5在输入序列的第五位,却在输出序列的第三位。这也就意味着,在输出5之后,输入在5之前且还未输出的数都在栈内,这一特征反映在输出序列中,就是
————————————
对于输出序列中的数字x而言:
对于所有满足:
1.输入位置在x之前
2.输出位置在x之后
的数字——
这样的数字在x输出之前一定已经在栈内了,所以必须服从栈的输出规律“后进先出”,也就是
——必须按照输入顺序的反序输出
————————————
在以上示例中,数字3和4的输入位置在5之前,而输出位置在5之后,所以它们应该按照输入顺序的反序输出,也就是“5 4 3”,但是示例中是“5 3 4”,所以该示例不能输出。

构思算法

创建变量:

变量名 类型 描述
inLen/outLen int 输入/输出序列长度
st/outst *int 动态数组存放输入顺序/输出顺序
curOrd int 现在验证的数据在输入序列中的顺序(下文不注明则顺序都指输入顺序)
preOrd int 上一个验证的数据的顺序
Ord int 已验证的数字中的最大顺序
flag bool 记录是否已经逆序(称两数输出次序和输入次序相反为逆序)输出一次

—————————————————————————————————
算法:
【虽然根据以上思路,看上去对于输出序列中的每一个数字,都要对它输出序列中更前的数字进行验证,但是实际上,由于条件1描述的是x之前所有的数字,且输出位置在x更靠后的数字之后,自然也在x之后,所以满足了输入序列中更靠后的数字的要求,就已经满足了前面所有数字的要求
1.将目前验证过的数字中顺序最靠后的数字的顺序存放在Ord中,上一个验证过的数字的顺序存放在preOrd中。
2.读入输出序列的下一个数字(记为y),并找出y在输入序列上的顺序,存放在变量curOrd(current order)中;
验证curOrd是否满足
1.curOrd>preOrd
2.flag==false(表示上次输出是反序输出)
3.curOrd<Ord
全满足则返回0。
————————————————————————————————
代码如下:

#include<iostream>

using namespace std;

int main()
{
   
    int inLen(0),outLen(0),preOrd(-1),Ord(-1),curOrd(0),cur(1),*st=NULL,*outst=NULL;//注意cur的开始值
    bool flag(true);

    //输入部分
    cin>>inLen
  • 12
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值