题目描述
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1 来表示。
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址是该结点的地址,键值是绝对值不超过104的整数,下一个结点是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
1 2 3 4 5 6
| 00100 5 99999 -7 87654 23854 -15 00000 87654 15 -1 00000 -15 99999 00100 21 23854
|
输出样例:
1 2 3 4 5
| 00100 21 23854 23854 -15 99999 99999 -7 -1 00000 -15 87654 87654 15 -1
|
分析:
node保存了节点的基本信息,当前地址now, 节点的值val, 下一个地址next, nodes[i]则存储地址i下的一个完整节点信息。
用next0保存节点的链式关系,遍历整条链,将val绝对值相同的筛选出来,这样得到两条链。
为了打印的时候重新建立链式关系,在打印v[i].next时,实际上每次打印的是容器中下一个元素的now,即v[i + 1].now,另外就是最后一个节点的next要设成-1。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include<iostream> #include<map> #include<cmath> #include<vector> #include<cstdio> using namespace std; const int maxn = 1e6 + 10; int vis[maxn], next0[maxn]; struct node { int now, val, next; } nodes[maxn]; void print(vector<node> &v) { for (int i = 0; i < v.size(); i++) { printf("%05d %d ", v[i].now, v[i].val); if (i + 1 < v.size()) printf("%05d", v[i + 1].now); else printf("-1"); if (i < v.size() - 1) printf("\n"); } } int main() { vector<node> v; int head, num; cin >> head >> num; while (num--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); next0[a] = c; nodes[a] = node {a, b, c}; } vector<node> v1, v2; for (int i = head; i != -1; i = next0[i]) { if (!vis[abs(nodes[i].val)]) { v1.push_back(nodes[i]); vis[abs(nodes[i].val)] = 1; } else { v2.push_back(nodes[i]); } } print(v1); printf("\n"); print(v2); return 0; }
|