在这里插入图片描述
在这里插入图片描述

思路(java 超时,c++可以过)

  1. 利用结点的地址,当做数组的索引,开一个存放结点键值的数组data,在开一个存放结点下一个结点地址的数组p,具体含义可见注释;
  2. 由于键值的绝对值不能重复,所以我们用一个vis数组去标记每个已经出现的数,用来处理重复的结点;
  3. 用两个容器去存放删去重复元素的新链表,以及被删去的结点的链表;注意这两个容器存的是结点的地址,通过这个结点的地址和data数组、p数组就可以获取到键值的信息、下一个结点地址的信息;
  4. 结点存放在这些数组后,我们通过p数组去处理这个链表,通过一个循环,i从输入中给出的头结点地址,然后循环结束条件就是处理到最后一个结点,地址为为-1;
  5. 处理当前的地址时,我们通过vis数组去判断是否重复,然后放到相应的容器中;然后让处理当前结点的下一个结点,也就是利用p数组去获取下一个结点的地址,也就是让i=p[i];
  6. 关于此题输出需要注意:
    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;
}
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐