之前写l2-22时用了双端队列,导致这个题开始写的时候一直想着用双端队列,其实只要把链表用队列存起来然后,用数组分别把链表不重复部分的编号和重复部分的编号存起来就行了,具体看代码
L2-002. 链表去重
时间限制
300 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点。即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留。同时,所有被删除的结点必须被保存在另外一个链表中。例如:另L为21→-15→-15→-7→15,则你必须输出去重后的链表21→-15→-7、以及被删除的链表-15→15。
输入格式:
输入第一行包含链表第一个结点的地址、以及结点个数N(<= 105 的正整数)。结点地址是一个非负的5位整数,NULL指针用-1表示。随后N行,每行按下列格式给出一个结点的信息:
Address Key Next
其中
Address是结点的地址,
Key是绝对值不超过104的整数,
Next是下一个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除结点组成的链表。每个结点占一行,按输入的格式输出。
输入样例:
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
#include<stdio.h>
#include<string.h>
#include<queue>
#include<deque>
#include<algorithm>
using namespace std;
// 结构体存储信息
struct data
{
int value;
int address;
int next;
}q[110000];
int main()
{
int head;
int n;
scanf("%d %d",&head,&n);
int x,y,z;
for(int i=0; i<n; i++)
{
scanf("%d %d %d",&x,&y,&z);
q[x].address = x;
q[x].value = y;
q[x].next = z;
}
int lin1[110000]; //存储去重后的链表
int lin2[110000]; //存储重复的链表
int book[110000]; //检查是否重复用
memset(book,0,sizeof(book));
int tt=head; //将链表用队列存起来
queue<data>qq;
while(tt !=-1)
{
qq.push(q[tt]);
tt = q[tt].next;
}
int ans1=0;
int ans2=0;
while(!qq.empty()) // 逐个取出链表结点并判断是否被标记
{
data temp;
temp = qq.front();
qq.pop();
if(book[abs(temp.value)] == 0) //没有被标记
{
book[abs(temp.value)] = 1;
lin1[ans1++] = temp.address; // 存进lin1
}
else
lin2[ans2++] = temp.address; //被标记过,存进lin2
}
// 输出比较麻烦
if(ans1 != 0)
{
for(int i=0; i<ans1; i++)
{
if(i+1 <ans1)
printf("%05d %d %05d\n",lin1[i],q[lin1[i]].value,lin1[i+1]);
}
printf("%05d %d -1\n",lin1[ans1-1],q[lin1[ans1-1]].value);
}
if(ans2 != 0)
{
for(int i=0; i<ans2; i++)
{
if(i+1 <ans2)
printf("%05d %d %05d\n",lin2[i],q[lin2[i]].value,lin2[i+1]);
}
printf("%05d %d -1\n",lin2[ans2-1],q[lin2[ans2-1]].value);
}
}