L2-002 链表去重 (25 分)
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 − 来表示。
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址
是该结点的地址,键值
是绝对值不超过1的整数,下一个结点
是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
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
PTA特色模拟题
一开始赋值nxt为-1 默认为没有后续节点 要是有后续节点 执行nxt[pre] = crt, 让上一次的指向当前节点
比赛的时候没写出来 写的还是挺有感觉的
1 using namespace std; 2 #include <stdio.h> 3 #include <iostream> 4 #include <algorithm> 5 int N, M, K, S; 6 const int si = 100100; 7 int val[si], nxt[si]; 8 bool vis[si]; 9 int snxt[si], dnxt[si]; 10 int sv[si], dv[si]; 11 int main() { 12 cin >> S >> N; 13 for (int i = 0; i < N; i++) { 14 int adr, v, b; 15 cin >> adr >> v >> b; 16 val[adr] = v; 17 nxt[adr] = b; 18 } 19 20 int crt = S, dstart = -1, spre = -1, dpre = -1; 21 while (crt != -1) { 22 int v = val[crt], n = nxt[crt]; 23 if (!vis[abs(v)]) { 24 vis[abs(v)] = 1; 25 if (spre != -1) { 26 snxt[spre] = crt; 27 } 28 snxt[crt] = -1;//下一个 29 sv[crt] = v;//v 30 spre = crt; 31 } 32 else { 33 if (dstart == -1) { 34 dstart = crt; 35 } 36 else { 37 dnxt[dpre] = crt; 38 } 39 dnxt[crt] = -1; 40 dv[crt] = v; 41 dpre = crt; 42 } 43 crt = n; 44 } 45 crt = S; 46 while (crt != -1) { 47 printf("%05d %d ", crt, sv[crt]); 48 if (snxt[crt] != -1) { 49 printf("%05d\n", snxt[crt]); 50 } 51 else { 52 printf("%d\n", snxt[crt]); 53 } 54 crt = snxt[crt]; 55 } 56 57 crt = dstart; 58 while (crt != -1) { 59 printf("%05d %d ", crt, dv[crt]); 60 if (dnxt[crt] != -1) { 61 printf("%05d\n", dnxt[crt]); 62 } 63 else { 64 printf("%d\n", dnxt[crt]); 65 } 66 crt = dnxt[crt]; 67 } 68 return 0; 69 }