題目描述
給定一個最大容量爲 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
思路分析
一開始使用鏈表遇到了很多問題,後來發現用數組會簡單很多。
這個題可以分爲三種情況來判斷:第一種就是,元素入棧之後立刻出棧,那麼出棧序列的順序還是1,2,…,n的順序;第二種情況就是前k個元素一直入棧,然後開始出棧,那麼出棧序列的順序就是k,k-1,……,1;第三種情況就是前面這兩種情況的結合。
退出循環的條件是i>n或者A滿了,但是判斷是否退出循環的先決條件是i不等於B和A的pop不等於B。
源代碼
#include<stdio.h>
int m,n,k;
int stack[1007]; //棧
int top=0; //棧頂下標
int index1=1,index2=1; //index1來表示1-n的數字 ,index2來表示數組b的下標
int b[1007]; //存放出棧序列
int main()
{
scanf("%d%d%d",&m,&n,&k);
while(k--)
{
int flag=1;
index1=1;index2=1;
top=0;
int i;
for(i=1;i<=n;i++)
scanf("%d",&b[i]);
while(1)
{
//判斷給出的出棧序列如果和1到n增長順序相同,那就是入棧一個元素,然後立即出棧。
if(index1==b[index2])
{
index1++;
index2++;
}
//判斷如果棧中有元素,然後棧頂元素也與此時的出棧序列元素相同,那麼就繼續出棧來判斷
else if(top!=0&&stack[top-1]==b[index2])
{
top--;
index2++;
}
else
{
if(index1>n)break; //已經判斷結束,就跳出循環
stack[top]=index1; //元素入棧
top++;
index1++;
if(top>=m) //
{
flag=0;
break;
}
}
}
if(flag==0||top!=0)printf("NO\n");
else printf("YES\n");
}
return 0;
}