一、题目
给定一个带整数键值的链表 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
二、方法1
1、思路
易错点提示:
- 其实用链表也可以,不过数组更加简单,思路都大同小异;
- 用数组的时候,在输入时,记得分开输入 t,num[t],loc[t] 这三个数据,如果同时输入,会导致 num[t],loc[t] 数据丢失;
- 在输出的时候,注意最后一个节点的下一个节点为NULL,用 -1 表示,但是在去重遍历时,数组内的数据仍为随机值,所以要单独输出;
- 根据题意,去重后的链表一定不为空,但是被删除的链表可能为空,所以输出时要判断一次。
2、代码
#include<stdio.h>
#include<math.h>
#define max 100005
int first, n;
int i, j; // 遍历
int t, k; // 中间值
int cnt_a = 0, cnt_b = 0; //
int num[max], loc[max], visit[max] = { 0 }, a[max], b[max];
int main()
{
scanf("%d %d", &first, &n);
for (i = 0; i < n; i++)
{
scanf("%d", &t);
scanf("%d %d", &num[t], &loc[t]);
}
k = first;
while (k != -1)
{
t = abs(num[k]);
if (visit[t] == 0)
{
visit[t] = 1;
a[cnt_a++] = k;
}
else
{
b[cnt_b++] = k;
}
k = loc[k];
}
for (i = 0; i < cnt_a - 1; i++)
{
printf("%05d %d %05d\n", a[i], num[a[i]], a[i + 1]);
}
printf("%05d %d -1\n", a[cnt_a - 1], num[a[cnt_a - 1]]);
if (cnt_b)
{
for (i = 0; i < cnt_b - 1; i++)
{
printf("%05d %d %05d\n", b[i], num[b[i]], b[i + 1]);
}
printf("%05d %d -1\n", b[cnt_b - 1], num[b[cnt_b - 1]]);
}
return 0;
}