给定一个带整数键值的链表 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
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
思路:其实就是一个和上个那个链表重排差不多的题目,一开始博主想用一般链表去重,也就是删除的原理(就是上一个结点的指针连到下一个结点的next指针上面)但是不知道为什么有三个测试点没过,后来想想其实只是需要将一个去重之后的存到一个数组里面,一个重复的存另一个数组里面其实就可以了,直接输出。
#include "bits/stdc++.h" using namespace std; const int N = 1e5 + 10; string s[N], nex[N]; int a[N], vis[N]; map<string , int> mp; vector<int> v, w, h; int main(){ string ss; int n, begin; string start = ss; cin>>ss>>n; for(int i = 0; i < n; i++){ cin>>s[i]>>a[i]>>nex[i]; mp[s[i]] = i; if(s[i] == ss) begin = i; } int now = begin; while(ss != "-1"){ v.push_back(now); ss = nex[now]; now = mp[nex[now]]; } int sizev = v.size(); int pre; for(int i = 0; i < v.size(); i ++){ int t = abs(a[v[i]]); if(!vis[t]) { vis[t] = 1; h.push_back(v[i]); } else { sizev --; // cout<<nex[pre] <<" " <<a[pre]<<" "<<nex[v[i]]<<"&&&"<<endl; w.push_back(v[i]); nex[pre] = nex[v[i]]; //nex[mp[nex[v[i]]]];//这是下一个结点的next } pre = v[i]; } now = begin; ss = start; // for(int i = 0; i < v.size(); i ++){ // int t = abs(a[v[i]]); // if(!vis[t]) { // vis[t] = 1; // // } // } for(int i = 0; i < h.size(); i++){ cout<<s[h[i]]<<" "<<a[h[i]]<<" "; if(i != h.size() - 1) cout<<s[h[i + 1]]<<endl; else cout<<"-1"; } // while(ss != "-1"){ // cout<<s[now]<<" "<<a[now]<<" "<<nex[now]; // ss = nex[now]; // now = mp[nex[now]]; // if(ss != "-1") cout<<endl; // } if(w.size() != 0) cout<<endl; for(int i = 0; i < w.size(); i++){ cout<<s[w[i]]<<" "<<a[w[i]]<<" "; if(i != w.size() - 1) cout<<s[w[i + 1]]<<endl; else cout<<"-1"; } return 0; }