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;
}