L2-002 链表去重 (25 分) java c++
思路(java 超时,c++可以过)利用结点的地址,当做数组的索引,开一个存放结点键值的数组data,在开一个存放结点下一个结点地址的数组p,具体含义可见注释;由于键值的绝对值不能重复,所以我们用一个vis数组去标记每个已经出现的数,用来处理重复的结点;用两个容器去存放删去重复元素的新链表,以及被删去的结点的链表;注意这两个容器存的是结点的地址,通过这个结点的地址和data数组、p数组就可以获取到
·
思路(java 超时,c++可以过)
- 利用结点的地址,当做数组的索引,开一个存放结点键值的数组data,在开一个存放结点下一个结点地址的数组p,具体含义可见注释;
- 由于键值的绝对值不能重复,所以我们用一个vis数组去标记每个已经出现的数,用来处理重复的结点;
- 用两个容器去存放删去重复元素的新链表,以及被删去的结点的链表;注意这两个容器存的是结点的地址,通过这个结点的地址和data数组、p数组就可以获取到键值的信息、下一个结点地址的信息;
- 结点存放在这些数组后,我们通过p数组去处理这个链表,通过一个循环,i从输入中给出的头结点地址,然后循环结束条件就是处理到最后一个结点,地址为为-1;
- 处理当前的地址时,我们通过vis数组去判断是否重复,然后放到相应的容器中;然后让处理当前结点的下一个结点,也就是利用p数组去获取下一个结点的地址,也就是让i=p[i];
- 关于此题输出需要注意:
6.1 如果用的是int存放地址的话,要注意前导0的处理,利用printf("%05d");
6.2 要注意经过处理后得到的两个新链表中的最后一个元素的next指针域为null,不再是原来的p数组中的值;所以我们要把每个链表的最后一个结点单独拿出来输出;
6.3 在输出每个结点的next域的值时,不能利用p数组了,因为p数组存放的是原链表的链接关系,但是现在已经经过去重的处理了,所以我们可以利用容器中的下一个元素的值,正好就是当前结点的next值;以去重的链表为例:
java:
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] p = new int[100000 + 5];//p[12345]=45678的值:地址为12345下一个结点的地址为45678
int[] data = new int[100000 + 5];//data[12345]=66的值:地址为12345处的键值为66
int[] vis = new int[100000 + 5];//标记键值是否出现过
ArrayList<Integer> newList = new ArrayList<>();//存放去重后的结点的地址,这样可以通过这个地址查到结点值data,以及下一个地址p
ArrayList<Integer> delete = new ArrayList<>();存放删去的的结点的地址,这样可以通过这个地址查到结点值data,以及下一个地址p
int start = sc.nextInt();
int n = sc.nextInt();
//存放这些结点
for (int i = 0; i < n; i++) {
int a = sc.nextInt();
int b = sc.nextInt();
int c = sc.nextInt();
data[a] = b;
p[a] = c;
}
//从第一个地址开始
for (int i = start; i != -1; i = p[i]) {//空地址 NULL 用 −1 表示
int d = Math.abs(data[i]);//当前的结点的键值
if (vis[d] == 0) {//这个结点不重复
vis[d] = 1;
newList.add(i);//把这个结点的地址添加进去
} else {//重复结点
delete.add(i);
}
}
//输出没有重复结点的新链表
for (int i = 0; i < newList.size() - 1; i++) {
int address = newList.get(i);
//输出时要注意删除结点会影响当前节点的下一个元素的地址,所以直接输出当前链表的下一个元素的地址
System.out.printf("%05d %d %05d\n", address, data[address], newList.get(i + 1));
}
//最后一个结点的下一个next为null,也就是-1
int temp = newList.get(newList.size() - 1);
System.out.printf("%05d %d %d\n", temp, data[temp], -1);
//输出删去的结点
for (int i = 0; i < delete.size() - 1; i++) {
int address = delete.get(i);
System.out.printf("%05d %d %05d\n", address, data[address], delete.get(i + 1));
}
//最后一个结点的下一个next为null,也就是-1
temp = delete.get(delete.size() - 1);
System.out.printf("%05d %d %d\n", temp, data[temp], -1);
}
}
c++
AC
#include<bits/stdc++.h>
using namespace std;
int d[100000 + 5];
int p[100000 + 5];
int vis[100000 + 5];
vector<int> newList;
vector<int> deleteList;
int main() {
int start, n;
cin >> start >> n;
while (n--) {
int a, b, c;
cin >> a >> b >> c;
d[a] = b;
p[a] = c;
}
for (int i = start; i != -1; i = p[i]) {
if (!vis[abs(d[i])]) {
newList.push_back(i);
vis[abs(d[i])] = 1;
} else {
deleteList.push_back(i);
}
}
for (int i = 0; i < newList.size(); i++) {
int address = newList[i];
if (i == ((newList.size() - 1))) {
printf("%05d %d %d\n", address, d[address], -1);
} else {
printf("%05d %d %05d\n", address, d[address], newList[i + 1]);
}
}
for (int i = 0; i < deleteList.size(); i++) {
int address = deleteList[i];
if (i == ((deleteList.size() - 1))) {
printf("%05d %d %d\n", address, d[address], -1);
} else {
printf("%05d %d %05d\n", address, d[address], deleteList[i + 1]);
}
}
return 0;
}
更多推荐
所有评论(0)