小练习记录贴04
点击跳转到原题
题目描述
给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。
输入格式
输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤
1
0
5
10^5
105,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL 用 −1 来表示。
随后 N 行,每行按以下格式描述一个结点:
地址 键值 下一个结点
其中地址是该结点的地址,键值是绝对值不超过 1 0 4 10^4 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
解题思路
map可以让两个数据类型产生关联,并且first当作索引,同时会自动排序(入股first是int或者string类型)。本题暂时用不到自动排序。pair应该也可以做到,但是目前我对pair的掌握程度不如map,所以这道题选择了使用map来做。
主要是创建了以下几个map:
- key_value(int, int): 将地址和数值匹配
- addrs(int, int):将地址和下一个地址匹配上
- values(int, bool):标记当前数值绝对值是否出现过
两个vector(int)保存保留的链表节点和删除的链表节点。
保存好原始数据之后,从第一个地址遍历链表,出现重复的数值放入link2(删除的链表节点),反之,加入link2,并且将数值存入values当中。
因为给了数据范围,地址范围在 1 0 5 10^5 105,数值绝对值范围在 1 0 4 10^4 104,所以有的coder也直接用数组做,大致思路是一样的。(假如我提前意识到地址是五位==范围在五位数,我大概率也会这样选择,然而……)
另外需要注意的是,假如所有的节点都被保留下来,那么删除节点链表就不用输出了,而不是输出-1. 所以后面还要多加一个判断,不加的话第三个节点过不去。
数值不使用map或数组标记,而是循环查找会有两个节点超时。
AC代码
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
using namespace std;
int main(){
int begin, N; cin >> begin >> N;
map<int, int> addrs;
map<int, int> key_value;
for(int i = 0; i < N; i ++){
int addr1, value, addr2;
cin >> addr1 >> value >> addr2;
addrs[addr1] = addr2;
key_value[addr1] = value;
}
map<int, bool> values;
vector<int> link1, link2;
int index = begin;
while(index != -1){
bool existValue = false;
if(values[abs(key_value[index])] == true){
existValue = true;
}
if(existValue){
link2.push_back(index);
}else{
link1.push_back(index);
//values.push_back(abs(key_value[index]));
values[abs(key_value[index])] = true;
}
index = addrs[index];
}
for(int i = 0; i < link1.size(); i ++){
if(i) printf(" %05d\n", link1[i]);
printf("%05d %d",link1[i], key_value[link1[i]]);
//cout << link1[i] << " " << key_value[link1[i]] << endl;
}
printf(" -1\n");
if(link1.size() == N) return 0;
for(int i = 0; i < link2.size(); i ++){
if(i) printf(" %05d\n", link2[i]);
printf("%05d %d",link2[i], key_value[link2[i]]);
}
printf(" -1\n");
return 0;
}