出栈序列的合法性 (25 分)
过去属于死神,未来属于你自己 ——《吞噬地球》
题目源自PAT浙大版《数据结构学习与实验指导(第2版)》题目集
基础实验3-2.4 出栈序列的合法性 (25 分)
给定一个最大容量为 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
思路:
看了许多判断出栈合法性的,判断出栈序列中的每个数后面的比它小的数,是按递减排列的(自己不太明白,觉得好复杂,感觉运行效率比较高,后期认真思考一下)。比较好理解的似乎是直接模拟出栈,运行效率会下降。
创建一个栈以及两个数组,一个数组a用来存放入栈顺序,一个数组b用来存放要判断的序列。
遍历数组a,把数组a的值入栈,将栈顶元素与数组b中第一个元素相比较,如果不一样,继续将数组a中下一个元素入栈;如果一样,将栈顶元素出栈,继续比较数组b中下一元素。
反复如此,直到数组a中元素遍历完一遍或者直到栈中元素个数大于所给的最大值结束循环。
最后判断栈中元素个数,如果为0,则说明是正确的,否则就是错的。
图解:
大致的图解是这样的,后面循环的就没再画了,为了防止看不懂,又画了个流程图。
流程图(如有错误,欢迎指正)
代码:
import java.util.Scanner;
import java.util.Stack;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int max= input.nextInt();//栈的最大容量
int sum= input.nextInt();//数字总数
int times= input.nextInt();//待检查序列个数
//int[] a=new int[sum];刚发现数组a似乎没用了
int[] b=new int[sum];
//对于此题这一部分也没用了
//for (int i = 0; i < sum; i++) {
// a[i]=i+1;
//}
for (int k = 0; k < times; k++) {
int flag=1;//用来作为提前跳出的标志1正常,0栈满
Stack<Integer> sta = new Stack<>();
for (int i = 0; i < sum ; i++) {
b[i]=input.nextInt();
}
for(int i=0,j=0;i<sum;i++){
sta.add(i+1);//sta.add(a[i]);这一句进行相应的修改
if(sta.size()>max){
flag=0;
break;
}
while (j<b.length&&sta.size()>0&&sta.peek()==b[j]){
++j;
sta.pop();
}
}
if(sta.size()==0&&flag==1){
System.out.println("YES");
}else {
System.out.println("NO");
}
}
input.close();
}
}