题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805072641245184
给定一个带整数键值的链表 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
分析:
每一个点有三个参数:本身的地址 权值 下一个点的地址
开结构体模拟链表的本质:把本身的地址当做数组的下标。然后可以通过for循环从头结点的地址遍历到最后
下标是地址:地址的范围为0~99999
还有最关键的一点:初始化:把0~99999内的num值都初始化为大于结点个数的值
这样处理以后,sort排序才能根据区间内的数把num从小到大排序,从而保证0~k为结点
代码:
#include<cstdio>
#include<cstring>
#include<math.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
const int N=1e5;
struct node
{
int address;
int key;
int net;
int num;/*排序*/
} root[N];
bool book[N];
int cmp(node x,node y)
{
return x.num<y.num;
}
int main()
{
int head,n;
scanf("%d%d",&head,&n);
for(int i=0; i<N; i++)
root[i].num=2*N;
memset(book,false,sizeof(book));
for(int i=0; i<n; i++)
{
int t1,t2,t3;
scanf("%d%d%d",&t1,&t2,&t3);
root[t1].key=t2;/*这个地方下标是地址*/
root[t1].net=t3;
root[t1].address=t1;
}
int k1=0,k2=0,k;
for(int i=head; i!=-1; i=root[i].net)
{
int t=fabs(root[i].key);
if(!book[t])
{
book[t]=true;
root[i].num=k1++;
}
else
{
root[i].num=N+k2;
k2++;
}
}
sort(root,root+N,cmp);/*root[i]每一个i表示地址,排序后把num小的排到了前面*/
k=k1+k2;
for(int i=0; i<k; i++)/*这里的i表示第i个数*/
{
if(i!=k1-1&&i!=k-1)
printf("%05d %d %05d\n",root[i].address,root[i].key,root[i+1].address);
else
printf("%05d %d -1\n",root[i].address,root[i].key);
}
return 0;
}