[PTA天梯赛出栈顺序

PTA天梯赛出栈顺序
多种写法,容器,数组

给定一个最大容量为 M 的堆栈,将 N 个数字按 1, 2, 3, …, N 的顺序入栈,允许按任何顺序出栈,则哪些数字序列是不可能得到的?例如给定 M=5、N=7,则我们有可能得到{ 1, 2, 3, 4, 5, 6, 7 },但不可能得到{ 3, 2, 1, 7, 5, 6, 4 }。

输入格式:

输入第一行给出 3 个不超过 1000 的正整数:M(堆栈最大容量)、N(入栈元素个数)、K(待检查的出栈序列个数)。最后 K 行,每行给出 N 个数字的出栈序列。所有同行数字以空格间隔。

输出格式:

对每一行出栈序列,如果其的确是有可能得到的合法序列,就在一行中输出YES,否则输出NO。

输入样例:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

输出样例:

YES
NO
NO
YES
NO

天梯赛模拟赛,唉,当时写的很复杂,改了很多次还是两三个样例没有过,看着写出来的人那么多,糟糕坏了。

下面一段是废话。

我最初的思路很一般,实现起来很麻烦,要判断的东西有很多,就是当你一个数出栈时,首先你需要判断此刻栈是不是已经满了,还要判断哪些元素已经出栈了,没有在栈内了,还要判断栈内的元素不能比出栈的元素大。就是循环套循环还加标记,要有多麻烦有多麻烦。
—————————————————————————

******其实很多时候用一般性思维去考虑时,往往会很麻烦,需要换一种新新的方式去想。

******题目中要我们判断出栈顺序是否合理,
我们就遵循题意,把一个一个元素从小到大入栈,当入栈元素与出栈元素相等时,我们家把该元素出栈,top–;然后继续放元素,如果我们把所有元素都可以放进去,那说明这个出栈顺序是合理的。
过程中会遇到的问题:

1.怎么判断栈已满。
-------根据top,top不仅代表栈顶,还代表栈内元素。我们虽然让元素一次入栈,执行++top,但同时,需要出栈的元素与栈内元素一致时,我们也会执行top–,出栈。因此,当top>m时,就可表示栈溢出了。

2.如何判断栈内元素存在比出栈元素大
这个问题无需考虑,因为是从小到大一次选择入栈的。

3.怎么知晓哪些元素已经出栈了
这个其实我们无需关心,top已经表示栈内元素个数了,就不用再关注哪些元素已出栈了

所以呢
利用该思想,操作起来就简单多了

———————-----------——————————————–

方法1:用数组来写

#include<stdio.h>
#include<string.h>
int a[1100],sta[1100];
int main()
{
	int m,n,k;
	scanf("%d %d %d",&m,&n,&k);
	while(k--)
	{
		int i,j;
		sta[0]=-1;//给sta[0]赋一个永远不可能与出栈元素相等的值 
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		int w=1,top=0;
		sta[++top]=w;//首先让1入栈
		i=1;
		while(i<=n)//按照出栈顺序让栈内元素出栈
		{
			while(a[i]==sta[top])//当前栈顶满足出栈要求,降低top
			{
				top--;//栈顶出栈
				i++;//新的栈顶与下一个将要出栈的元素进行对比
	          //下面的可以不需要,因为sta[0]==-1
        	  //if(top==0)//栈内无元素了,不可能再出栈了
	          //	break; 
			}
            //栈顶元素小于要出栈的元素,说明此刻要出栈的元素还没有进栈呢
            //出栈元素要进栈,那比它小的肯定得比它先进栈
			if(a[i]!=sta[top])
			{
				sta[++top]=++w;//注意++w,用意在于进过栈的元素不可能二次进栈,无论是未出栈的,还是出过栈的,进栈机会只有一次 
			}
			if(top>m||w>n)//栈溢出,或者所有的元素都进栈了
				break; 
		}
		//出栈顺序合法,栈顶最终指向1
		if(i==n+1)//当然只有当所有出栈顺序和合法的时候才YES,这一条件是必须的
			printf("YES\n");//所有出栈顺序合法,没有问题 
		else
			printf("NO\n"); 
	} 
}

方法2:用容器来写

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
using namespace std;
int a[1010];
stack<int>st;//容器栈,先进后出 
int main()
{
	int m,n,k;
	scanf("%d %d %d",&m,&n,&k);
	while(k--)
	{
	
		int i,w=1;
		for(i=1;i<=n;i++)
			scanf("%d",&a[i]);
		
		while(!st.empty())
			st.pop(); 
	
		st.push(w);//从1开始进栈 
	
		i=1;
		while(i<=n)//一个一个判定合法顺序 
		{
			while(a[i]==st.top())
			{
				st.pop();//删除栈顶元素
				i++;
				if(st.empty()!=0)//栈为空了就可以跳出循环了 
					break; 
			}
			if(st.empty()!=0||a[i]!=st.top())
			{
				st.push(++w);
			}
			if(st.size()>m||w>n)
				break; 
		}
		if(i==n+1)
			printf("YES\n");
		else
			printf("NO\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Helinshan/article/details/110679794