L2-002 链表去重 (25 分)
题目
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 −1 来表示。
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址
是该结点的地址,键值
是绝对值不超过104的整数,下一个结点
是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
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
思路
模拟链表即可(说的简单qwq)
开始用 map<string, string>
来存储地址(因为有前缀0),结果超时了,看了大佬的代码才发现自己想复杂了,用格式化输出就可以了。
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e6 + 19;
const ll mod = 1e9 + 7;
int nxt[N];
int data[N];
int delnxt[N];
int deldata[N];
int vis[N];
int main()
{
int n;
int head;
int delhead = -1;
int deltail = -1;
cin >> head >> n;
for(int i = 0; i < n; i++)
{
int pos, next;
int dat;
cin >> pos >> dat >> next;
data[pos] = dat;
nxt[pos] = next;
}
for(int i = head, pre = -1; i != -1; i = nxt[i])
{
if(vis[abs(data[i])])
{
if(pre == -1)
head = nxt[i];
else
nxt[pre] = nxt[i];
if(delhead == -1)
delhead = i;
deldata[i] = data[i];
if(deltail != -1)
delnxt[deltail] = i;
deltail = i;
}
else
{
vis[abs(data[i])] = 1;
pre = i;
}
}
delnxt[deltail] = -1;
for(int i = head; i != -1; i = nxt[i])
{
printf("%05d %d ", i, data[i]);
if(nxt[i] == -1)
{
printf("-1\n");
}
else
{
printf("%05d\n", nxt[i]);
}
}
for(int i = delhead; i != -1; i = delnxt[i])
{
printf("%05d %d ", i, deldata[i]);
if(delnxt[i] == -1)
{
printf("-1\n");
}
else
{
printf("%05d\n", delnxt[i]);
}
}
return 0;
}