L2-002. 链表去重

Posted 我只有一件白T恤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了L2-002. 链表去重相关的知识,希望对你有一定的参考价值。

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

思路:利用结构体数组保存链表,然后在进行遍历的时候,用set来判断是否已经存在于之前遍历的链表,如果出现了则移到另一个删除链表中,每次更新
链表的pre和dpre这两个分别用于保存前驱和删除链表的之后一个结点,但是第三个测试点运行超时。然后改成了用另外的结构体数组来保存被删除的结点,
在第一个原结构体数组中只要重复出现就删除,这样省时了很多。
技术分享图片
#include<set>
#include<cmath>
#include<cstdio>
#include<iostream>
using namespace std;
struct Node{
    int key;
    int next;
}list[100005], de[1000005];
int main()
{
    set<int>se;
    int begin, n; 
    int vis[100005];
    cin >> begin >> n;
    scanf("%d%d", &begin, &n);
    for (int i = 0; i < n; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        
        list[a].key = b;
        list[a].next = c;
    }
    int s = begin, flag = 0, debegin, pre = begin,dpre;
    while (s != -1)
    {
        if (se.find(abs(list[s].key)) == se.end()){
            se.insert(abs(list[s].key));
        
            pre = s;
            s = list[s].next;
        }
        else {
            if (flag == 0){
                debegin = s;
                flag++;

                de[s].key = list[s].key;
                de[s].next = -1;
                dpre = s;
            }
            else{
                de[s].key = list[s].key;
                de[dpre].next = s;
                de[s].next =- 1;
                dpre = s;
            }
            list[pre].next = list[s].next;
            s = list[s].next;
        }
    }
    s = begin;
    while (s != -1){
        printf("%05d %d ", s, list[s].key);
        if (list[s].next == -1)cout << "-1" << endl;
        else printf("%05d\n", list[s].next);
        s = list[s].next;
    }
    s = debegin;
    while (s != -1){
        printf("%05d %d ", s, de[s].key);
        if (de[s].next == -1)cout << "-1" << endl;
        else printf("%05d\n", de[s].next);
        s = de[s].next;
    }
    return 0;
}
运行超时代码

 

#include<set>
#include<cmath>
#include<map>
#include<iostream>
using namespace std;
struct Node{
    int key;
    int next;
}list[100005];
struct Delete{
    int here;
    int key;
}de[100005];
int main()
{
    set<int>se;
    int begin, n;
    cin >> begin >> n;
    for (int i = 0; i < n; i++)            //进行初始化
    {
        int a, b, c;
        cin >> a >> b >> c;
        list[a].key = b;
        list[a].next = c;
    }
    int s = begin, pre, delen = 0;
    while (s != -1){
        if (se.find(abs(list[s].key)) == se.end()){
            se.insert(abs(list[s].key));
            pre = s;
            s = list[s].next;
        }
        else {
            de[delen].here = s;
            de[delen++].key = list[s].key;

            list[pre].next = list[s].next;
            s = list[s].next;
        }
    }

    s = begin;
    while (s != -1){
        printf("%05d %d ", s, list[s].key);
        if (list[s].next == -1)cout << "-1" << endl;
        else printf("%05d\n", list[s].next);
        s = list[s].next;
    }
    for (int i = 0; i < delen; i++)
    {
        if (i != delen - 1)
            printf("%05d %d %05d\n", de[i].here, de[i].key, de[i + 1].here);
        else printf("%05d %d -1\n", de[i].here, de[i].key);
    }
    return 0;
}

 

 今天写题有点儿压抑,似乎需要一点儿鸡汤补补







以上是关于L2-002. 链表去重的主要内容,如果未能解决你的问题,请参考以下文章

L2-002 链表去重 (25 分)

L2-002 链表去重(链表+模拟)

L2-002 链表去重 (25 分)

L2-002. 链表去重(模拟)

PTA团体程序设计天梯赛-练习集 L2题目总结(完)

L2-2. 链表去重