L2-002 链表去重 模拟

L2-002 链表去重 (25 分)


给定一个带整数键值的链表 \(L\),你需要把其中绝对值重复的键值结点删掉。即对每个键值 \(K\),只有第一个绝对值等于 \(K\) 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 \(L\)\(21→-15→-15→-7→15\),你需要输出去重后的链表 \(21→-15→-7\),还有被删除的链表 \(-15→15\)


输入格式

输入在第一行给出 \(L\) 的第一个结点的地址和一个正整数 \(N\)\(\leqslant 10^5\),为结点总数)。一个结点的地址是非负的 \(5\) 位整数,空地址 NULL 用 \(−1\) 来表示。

随后 \(N\) 行,每行按以下格式描述一个结点:

地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过\(10^4\)的整数,下一个结点是下个结点的地址。


输出格式

首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。


输入样例

00100 5
99999 -7 87654
23854 -15 00000
87654 15 -1
00000 -15 99999
00100 21 23854

输出样例

00100 21 23854
23854 -15 99999
99999 -7 -1
00000 -15 87654
87654 15 -1

作者:陈越
单位:浙江大学
代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB



Solution

思路来自跃鱼的 L2-002 链表去重 (25分)

1.直接用 结构体数组 保存链表信息;

2.注意到只需要判断 键值的绝对值 是否出现过,使用vis[]记录即可;

3.用另外两个 结构体数组 保存去重后的链表、被删除的链表;

4.这样就不用考虑维护链表的下一个地址,因为下一个地址就是 结构体数组中 下一个结构体 保存的地址;

5.注意每个链表末尾都 链接 空地址 即可;


Solution

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=100005;
struct node{
	int now,w,nxt;
}list[N],ans1[N],ans2[N];
bool vis[N];
int ST,n,cnt1,cnt2;
int main(){
	scanf("%d %d",&ST,&n);
	for(int now,w,nxt,i=1;i<=n;++i){
		scanf("%d %d %d",&now,&w,&nxt);
		list[now].now=now;
		list[now].w=w;
		list[now].nxt=nxt;
	}
	for(int i=ST;i!=-1;i=list[i].nxt){
		if(!vis[abs(list[i].w)]){
			vis[abs(list[i].w)]=1;
			ans1[++cnt1]=list[i];
		} else 
			ans2[++cnt2]=list[i];
	}
	for(int i=1;i<=cnt1;++i){
		if(i!=cnt1) printf("%05d %d %05d\n",ans1[i].now,ans1[i].w,ans1[i+1].now);
		else printf("%05d %d %d\n",ans1[i].now,ans1[i].w,-1);
	}
	for(int i=1;i<=cnt2;++i){
		if(i!=cnt2) printf("%05d %d %05d\n",ans2[i].now,ans2[i].w,ans2[i+1].now);
		else printf("%05d %d %d\n",ans2[i].now,ans2[i].w,-1);
	}
	return 0;
}
posted @ 2021-03-10 22:28  PotremZ  阅读(492)  评论(0编辑  收藏  举报