洛谷线性结构训练(2):链表的insert,erase,find---P1739 表达式括号匹配,P1160 队列安排

P1739 表达式括号匹配

用了一个计数器计数,出现异常情况跳出。结果根据计数器判断。
题目描述
假设一个表达式有英文字母(小写)、运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回“YES”;否则返回“NO”。表达式长度小于255,左圆括号少于20个。

输入格式
一行:表达式

输出格式
一行:“YES” 或“NO”

输入输出样例
输入 #1复制
2*(x+y)/(1-x)@
输出 #1复制
YES
输入 #2复制
(25+x)(a(a+b+b)@
输出 #2复制
NO

#include<iostream>
using namespace std;
int main() {
	char expression[300];
	cin >> expression;
	int flag = 0;
	for (int i = 0; expression[i] != '\0'; i++) {
		if (expression[i] == '(')flag++;
		if (expression[i] == ')')flag--;
		if (flag < 0)break;
	}
	if (flag == 0)cout << "YES";
	else cout << "NO";
	return 0;
}
P1160 队列安排
本题总结:
1. 链表的使用

这题主要是训练了关于链表的STL的使用,另外还学习了如何使用打表的方法来对链表的读取进行加速
链表的一些常用的方法在下面进行简要说明:

//建立链表
list<int> l={1};//建立一个1个元素的链表,只含有元素1;

//链表的元素查找
int k;
auto iter = find(l.begin(),l.end(),k);//从链表中查找元素值为k的迭代器,将这个迭代器返回到iter

//链表插入
l.insert(iter,k);//在iter这个迭代器前插入元素k,该函数执行完后返回插入元素的迭代器

//链表迭代器的移动,这一部分可以和插入一起使用
auto n=next(iter);//next方法在<iterator>中,将链表后移一位
auto p=prev(iter);//prev方法也在iterator中,将链表前移一位
auto advan=advance(iter,n);//将链表移动n位,如果n是负数就向前移动

//链表删除
l.erase(iter);//删除iter所指向的元素,删除后链表自动拼接。

//merge
a.merge(ilist b);//将ab链表合并

//拆分链表
list1.splice(iter1,list2);//将链表1从iter1开始分开,将list2插入其中
list2.splice(list2.begin(),iter1,it,list1.end());//向list2中插入
2. 链表查找的优化

由于每次使用find(iter1,iter2,ElementToFind)的时候都是线性查找,时间很慢。因此定义了一个迭代器数组,利用它来进行查找,对于要删除的量,使用了一个bool数组来进行查询。

list<int>::iterator  pos[10000];// 迭代器赋值
pos[1]=l.begin();

//插入或者删除的时候只需如下操作
l.insert(pos[i],j);//向第i个元素的对应的迭代器前插入元素j

题目描述
一个学校里老师要将班上N个同学排成一列,同学被编号为1∼N,他采取如下的方法:

先将1号同学安排进队列,这时队列中只有他一个人;

2-N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为 1∼(i−1)中某位同学(即之前已经入列的同学)的左边或右边;

从队列中去掉M(M<N)M个同学,其他同学位置顺序不变。

在所有同学按照上述方法队列排列完毕后,老师想知道从左到右所有同学的编号。

输入格式
第1行为一个正整数N,表示了有N个同学。

第2-N行,第i行包含两个整数k,p,其中k为小于i的正整数,p为0或者1。若p为0,则表示将ii号同学插入到k号同学的左边,p为1则表示插入到右边。

第N+1行为一个正整数M,表示去掉的同学数目。

接下来M行,每行一个正整数x,表示将x号同学从队列中移去,如果xx号同学已经不在队列中则忽略这一条指令。

输出格式
1行,包含最多NN个空格隔开的正整数,表示了队列从左到右所有同学的编号,行末换行且无空格。

输入输出样例
输入 #1复制
4
1 0
2 1
1 0
2
3
3
输出 #1复制
2 4 1

说明/提示
样例解释:

将同学22插入至同学11左边,此时队列为:

2 121

将同学33插入至同学22右边,此时队列为:

2 3 1231

将同学44插入至同学11左边,此时队列为:

2 3 4 12341

将同学33从队列中移出,此时队列为:

2 4 1241

同学33已经不在队列中,忽略最后一条指令

最终队列:

2 4 1241

数据范围

对于20%20%的数据,有N≤10N≤10;

对于40%40%的数据,有N≤1000N≤1000;

对于100%100%的数据,有N, M≤100000N,M≤100000。

代码

#include<iostream>
#include<algorithm>
#include<list>
#include<iterator>
using namespace std;

int main() {
	int N;
	cin >> N;
	list<int> l = { 1 };
	int k, p;
	list<int>::iterator pos[100005];
	bool Erase[100005] = {};
	pos[1] = l.begin();
	for (int i = 2; i <= N; i++) {
		cin >> k >> p;
		//auto iter = find(l.begin(), l.end(), k);//找到k这个值的迭代器;但是这个线性查找太慢了,我们用一个打表的方法来优化
		if (p == 0) {//左边插入
			pos[i]=l.insert(pos[k], i);
		}
		else {//右边插入
			//advance(iter, 1);
		    pos[i]=l.insert(next(pos[k]), i);//next是iterator里面的方法
		}
	}
	int M;
	cin >> M;
	for (int i = 0; i < M; i++) {
		cin >> k;
		if (Erase[k] == false) {
			l.erase(pos[k]);
			Erase[k] = true;
		}
	}
	//for (int i = 0; i < M; i++) {
	//	cin >> k;
	//	auto iter=find(l.begin(), l.end(), k);
	//	if(iter!=l.end())
	//	l.erase(iter);
	//}
	for (auto x : l) {
		cout << x << " ";
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值