7-9 One Way In, Two Ways Out (25 分)

Consider a special queue which is a linear structure that allows insertions at one end, yet deletions at both ends. Your job is to check, for a given insertion sequence, if a deletion sequence is possible. For example, if we insert 1, 2, 3, 4, and 5 in order, then it is possible to obtain 1, 3, 2, 5, and 4 as an output, but impossible to obtain 5, 1, 3, 2, and 4.

Input Specification:

Each input file contains one test case. For each case, the first line gives 2 positive integers N and K (≤10), which are the number of insertions and the number of queries, respectively. Then N distinct numbers are given in the next line, as the insertion sequence. Finally K lines follow, each contains N inserted numbers as the deletion sequence to be checked.

All the numbers in a line are separated by spaces.

Output Specification:

For each deletion sequence, print in a line yes if it is indeed possible to be obtained, or no otherwise.

Sample Input:

5 4
10 2 3 4 5
10 3 2 5 4
5 10 3 2 4
2 3 10 4 5
3 5 10 4 2

Sample Output:

yes
no
yes
yes

中文翻译: 

考虑一个特殊的队列,它是一个线性结构,允许一端插入,两端都有删除。您的工作是检查给定的插入序列是否可以删除序列。例如,如果我们按顺序插入1、2、3、4和5,则可以获得1、3、2、5和4作为输出,但不可能获得5、1、3、2和4。

输入规格:

每个输入文件包含一个测试用例。对于每种情况,第一行给出2个正整数N和K(≤10) ,分别是插入数和查询数。然后在下一行中给出N个不同的数字,作为插入序列。最后是K行,每行包含N个插入的数字作为要检查的删除序列。

一行中的所有数字都用空格分隔。

输出规格:

对于每个删除序列,如果确实可以获得,则在行中打印“是”,否则打印“否”。

样本输入:

首先我们先去理解题意,比方说1234为默认序列,然后他给了个4123这个序列,那么就是按照4123的顺序删除其中的数据,4之前必须有123,3之前必须有12........,然后插入只能是一端,先是4,那么我们从一端插入1234,之后两端删除,先是4,从右面删除,然后是1,从左面删除,然后是2,从左面删除,然后是3从右面删除。同时如果一个数被删除之后,那么在后面的序列我们就不需要考虑这个数了,比方说2删除了,那么3之前的就只要有1即可。

从上面的一个例子我们是先判断一个数,他之前是要先出现哪些数的,我们现需要构造一个顺序函数,即某个数字出现之前,要出现那些数字,同时,我们还需要一个数组来标记一个数字是否已经被删除,还要判断两端的是否为对应的数(即我们要删除的数),如果不是那么就是NO。根据这一个我们写出了如下的代码:

#include <stdio.h>
int main(){
	int i,j;
	int k,n,front,flag,m,t,rear;
	scanf("%d%d",&n,&k);
	int a[n],c[n],b[n],book[n],g,h,l;//c[n]是存储当前的未删除的数字,a[n]就是顺序数组,b[n]就是我们要删除数字的顺序。
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);
		book[i]=1;//所有数据都还未被删除
		c[i]=-1;//防止随机数据和我们要删除的数据重复
	}
	for(i=0;i<k;i++){
		front=0;
		flag=0;
		l=0;
		rear=-1;//添加一个数据是从0下标开始的,所以我们让rear是-1
		for(j=0;j<n;j++)book[j]=1;
		for(j=0;j<n;j++){
			h=0;
			scanf("%d",&b[j]);//输入要加入的数据
			for(g=0;g<n;g++)if(a[g]==b[j])break;//找到该数据在a数组中的位置,方便下面先存入他前面的数据
			if(l<=g){for(m=0,l=0;l<=g;l++){//如果要存入的数据大于前面已经有的数据,我们就需要更新数组。
				if(book[l]==0)continue;//如果已经被删除就不执行
				c[h++]=a[l];
				front=0;//因为数组是往0上面插入的,所以我们就让头重新变成0.
			}
			rear=h-1;
		}
			if(c[front]==b[j]){//看头部是否为要删除的数据
				book[g]=0;
				front++;//删除头部,由于再内存中并没有删除,所以我们需要在逻辑上让front++,来达到逻辑上的删除。
			}
			else if(c[rear]==b[j]){//看尾部是否为要删除的数据
				book[g]=0;
				rear--;
			}
			else {j++;//都不是就是no
			flag=1;
			break;
			}
		}
		for(t=j;t<n;t++)scanf("%d",&b[t]);//由于break,导致一些数据未被scanf,所以在这里再用一个循环接受该数据。
		if(flag)printf("no\n");
		else printf("yes\n");
	}
}

 我写出来的代码只是逻辑上删除了数据,但是在内存上并没有将数据删除干净。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值