56行不到即可AC
思路:(看这里!看这里!
【原来】对于原表数据很麻烦的删去重复的元素(同时挪到另外一个数组里面),还要更改原表后面数据的地址,比较麻烦,时间复杂度也很高。
【现在】一个重点是:并不需要数据的下一个地址next了。
- 换到表里面是顺序存储,直接输出的时候输出下一个的地址即可。
- 采用了二维数组实现,【0】是当前数据的地址,【1】是当前数据值。
- 采用v【数据值】找寻该值是否已经存在,不存在就挪到留下来的二维数组里面;存在就挪到删去数据的二维数组内。
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K
的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表
21→-15→-7,还有被删除的链表 -15→15。
输入格式:
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤10 5 ,为结点总数)。一个结点的地址是非负的 5 位整数,空地址
NULL 用 -1 来表示。 随后 N 行,每行按以下格式描述一个结点:地址 键值 下一个结点 其中地址是该结点的地址,键值是绝对值不超过10 ^ 4 的整数,下一个结点是下个结点的地址。
输出格式:
首先输出去重后的链表,然后输出被删除的链表。每个结点占一行,按输入的格式输出。
输入样例:
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
(结尾无空行)
我的AC代码:
#include<bits/stdc++.h>
#include<string.h>
using namespace std;
struct {
int data;
int next;
}a[100012];
int main(){
int n,address,num,i,j,k,p;
cin>>address>>n;
int a_add[n]; //原已排好序的地址
int number[n];//是用来存原数据
bool v[10005]={0};//是用来遍历数据是否重复
int left_add[n][2];//用来存绝对值相同的数字
int remain_add[n][2];//留下的数据
for(i=0;i<n;i++){
int da,ne;
cin>>num>>da>>ne;//填入地址、数据、下一个结点
a[num].data=da;
a[num].next=ne;
}
for(address,j=0;address!=-1;j++){
a_add[j]=address;
number[j]=a[address].data;//顺序存储
address=a[address].next;
}
i=0,k=0,p=0;
//----------------------------------------------------
while(i<j) {
if(v[abs(number[i])]){//已经纯在过了
left_add[k][0]=a_add[i];//存地址
left_add[k][1]=number[i];//第二项存数据
k++;
}else{
remain_add[p][0]=a_add[i];//存地址
remain_add[p][1]=number[i];//第二项存数据
p++;
v[abs(number[i])]=1;
}
i++;
}
//先输出去重后链表
for(int i=0;i<p;i++){
if(i==p-1)printf("%05d %d -1\n",remain_add[i][0],remain_add[i][1]);
else printf("%05d %d %05d\n",remain_add[i][0],remain_add[i][1],remain_add[i+1][0]);
}
//再输出删除的链表
for(int i=0;i<k;i++){
if(i==k-1)printf("%05d %d -1",left_add[i][0],left_add[i][1]);
else printf("%05d %d %05d\n",left_add[i][0],left_add[i][1],left_add[i+1][0]);
}
return 0;
}
之前运行超时的代码:(虽然我觉得没有人会看但是还是放上来了)
#include<bits/stdc++.h>
#include<string.h>
using namespace std;
struct {
int data;
int next;
}a[100012];
int main(){
int n,address,num,i,j,k=0;
cin>>address>>n;
int a_add[n]; //是不是一个地址就够了orz不行啊
int number[n];//是用来存数据
int left_add[n][2];//用来存绝对值相同的数字
for(i=0;i<n;i++){
int da,ne;
cin>>num>>da>>ne;//填入地址、数据、下一个结点
a[num].data=da;
a[num].next=ne;
}
for(address,j=0;address!=-1;j++){
a_add[j]=address;
number[j]=a[address].data;//顺序存储
address=a[address].next;
}
i=0,k=0;
//----------------------------------------------------
while(i<j) {
int flag=0;
//此时的数字是a_add[i]首地址
for(int m=0;m<i;m++){
if(number[m]==number[i]||number[m]+number[i]==0){
flag=1;
break;
}
}//检验是否有重复的,有的话直接出来
if(flag){
//转存到被删除表中
left_add[k][0]=a_add[i];//存地址
left_add[k][1]=number[i];//第二项存数据
a[a_add[i-1]].next=a[a_add[i]].next;
//删除a_add【i】
for(int p=i;p<j-1;p++){
a_add[p]=a_add[p+1];
number[p]=number[p+1];
}
j--;
k++;
continue;
}
i++;
}
//先输出去重后链表
for(int i=0;i<j;i++){
if(i==j-1)printf("%05d %d -1\n",a_add[i],a[a_add[i]].data);
else printf("%05d %d %05d\n",a_add[i],a[a_add[i]].data,a_add[i+1]);
}
//再输出删除的链表
for(int i=0;i<k;i++){
if(i==k-1)printf("%05d %d -1",left_add[i][0],left_add[i][1]);
else printf("%05d %d %05d\n",left_add[i][0],left_add[i][1],left_add[i+1][0]);
}
return 0;
}