首页 > 其他分享 >天梯赛-练习集-L2-002 链表去重(25分)

天梯赛-练习集-L2-002 链表去重(25分)

时间:2024-04-11 20:12:47浏览次数:19  
标签:25 结点 15 temp 002 int 链表 start

L2-002 链表去重

代码长度限制:16 KB
时间限制:400 ms
内存限制:64 MB

题目描述

给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉。即对每个键值 K,只有第一个绝对值等于 K 的结点被保留。同时,所有被删除的结点须被保存在另一个链表上。例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15。

输入格式

输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤1e5,为结点总数)。一个结点的地址是非负的 5 位整数,空地址 NULL−1 来表示。

随后 N 行,每行按以下格式描述一个结点:

地址 键值 下一个结点

其中地址是该结点的地址,键值是绝对值不超过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

笔者观点

  • 做之前:这道题看着还是相当简单的,感觉拿stl就可以把它给秒了
  • 做之后:坏了!有坑!

具体思路

首先读入,用地址找键值,用一个map来存太合适不过了。然后建立两个链表,一个存留下的,一个存删除的,把map里面的东西过一遍,这题基本上就过了。估计一下复杂度map有一个log,同时我使用了一个set来判断是否元素是否存重复,也是一个log。所以复杂度为O(nlog)。(笔者看着64M的内存限制收敛不住嘴角,于是开了很多容器,把一道简单的题的内存和时间基本都吃满了)
同时这个题有一个比较坑的地方,给出的输入并不一定可以从头到尾练成一整条链,当你判断到下一个地址为NULL的时候,你就知道你该停下来了。(笔者因为这一点死死卡在测试点一,以泪洗面)

关键的地方

node为链表的节点的结构体,ci为当前地址,ne为下一个节点的地址。q是用来读入的mapsaveremovee分别为剩下的和删去的两条链表。(由于remove好像撞关键字了,所以加了一个e)

struct node
{
    string ci;
    int v;
    string ne;
};
map<string, pair<int, string>> q;
set<int> s;
list<node> save;
list<node> removee;
int saveNumber = 0;
int removeNumber = 0;

这里是两条链表的建立,不断更新start来遍历,用set< int >s来判断键值是否重复出现过,如果没有出现过,则放入save链表,同时放入s;如果出现过则放入removee链表,同时每次操作要更改操作链表的最后一个成员的下一个成员的地址的值

 for (int i = 0; i < asd; i++)
    {
        node temp;
        temp.ci = start;
        temp.v = q[start].first;
        temp.ne = q[start].second;

        if (s.count(abs(q[start].first)))  //判断是否出现过
        {
            (*removee.rbegin()).ne = temp.ci;  //改变链表最后元素的下一个地址的值
            removee.push_back(temp);      
            removeNumber++;
        }
        else
        {
            (*save.rbegin()).ne = temp.ci;  //改变链表最后元素的下一个地址的值
            s.insert(abs(q[start].first));
            save.push_back(temp);
            saveNumber++;
        }
        start = q[start].second;
        if (start == "-1")    //敲黑板,非常关键的地方,当读到-1的时候,链表就结束了,该退出了(如果你测试点一挂了,大概也是这里的锅)
            break;
    }

链表的输出,以removee链表为例,save链表的输出和它是一样的。注意最后一个成员的输出。

cnt = 0;
    for (auto it = removee.begin(); it != removee.end(); it++)
    {
        cnt++;
        if (cnt >= removeNumber)
            break;
        cout << (*it).ci << ' ' << (*it).v << ' ' << (*it).ne << endl;
    }
    if (removeNumber >= 1)
    {
        cout << (*removee.rbegin()).ci << ' ' << (*removee.rbegin()).v << " -1" << endl;
    }

完整代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct node
{
    string ci;
    int v;
    string ne;
};
map<string, pair<int, string>> q;
set<int> s;
list<node> save;
list<node> removee;
int saveNumber = 0;
int removeNumber = 0;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int asd;
    string start;
    cin >> start >> asd;
    for (int i = 0; i < asd; i++)
    {
        string here, there;
        int value;
        cin >> here >> value >> there;
        q[here].first = value;
        q[here].second = there;
    }

    for (int i = 0; i < asd; i++)
    {
        node temp;
        temp.ci = start;
        temp.v = q[start].first;
        temp.ne = q[start].second;

        if (s.count(abs(q[start].first)))
        {
            (*removee.rbegin()).ne = temp.ci;
            removee.push_back(temp);
            removeNumber++;
        }
        else
        {
            (*save.rbegin()).ne = temp.ci;
            s.insert(abs(q[start].first));
            save.push_back(temp);
            saveNumber++;
        }
        start = q[start].second;
        if (start == "-1")
            break;
    }

    int cnt = 0;
    // cout << "save" << endl;

    for (auto it = save.begin(); it != save.end(); it++)
    {
        cnt++;
        if (cnt >= saveNumber)
            break;
        cout << (*it).ci << ' ' << (*it).v << ' ' << (*it).ne << endl;
    }
    if (saveNumber >= 1)
    {
        cout << (*save.rbegin()).ci << ' ' << (*save.rbegin()).v << " -1" << endl;
    }

    // cout << "remove" << endl;
    cnt = 0;
    for (auto it = removee.begin(); it != removee.end(); it++)
    {
        cnt++;
        if (cnt >= removeNumber)
            break;
        cout << (*it).ci << ' ' << (*it).v << ' ' << (*it).ne << endl;
    }
    if (removeNumber >= 1)
    {
        cout << (*removee.rbegin()).ci << ' ' << (*removee.rbegin()).v << " -1" << endl;
    }

    return 0;
}

结果

时间消耗并不是很乐观(350ms/400ms),空间剩余还挺多的。用的编译器是C++ (clang++),最开始用的g++好像没过编译,而且好像有一点点不稳定?我同一份代码提交了三次,第二次竟然TLE了。总之这个解法似乎并不是很优越。

标签:25,结点,15,temp,002,int,链表,start
From: https://www.cnblogs.com/acidbarium/p/18129922

相关文章

  • P8725 [蓝桥杯 2020 省 AB3] 画中漂流
    题目:链接:https://www.luogu.com.cn/problem/P8725思路:dp[i][j]表示第i个时刻还有多少体力之前的错误思路:dp[i][j][k]表示第i个时刻,在j位置,有k个体力。但是注意:这三个变量并不是相互独立!!动规的一个取变量原则应该是相互独立确定某个状态。剩下k体力和i时刻可以推出位置!!site......
  • 面相对象(三):模拟链表
    面向对象的基本原理是对对象建模,让抽象的逻辑封装成具象的行为,更方便人们理解和使用。在前面的文章中我写了关于继承的一些理解,一般来说这里应该讨论与继承同为面向对象三个主要特征的多态与封装了。但是我想多态与封装是一种伴随着类的定义自然而然形成的现象,只有先接触了一定数......
  • 数据结构之链表(c语言版)
    链表是线性表,链表的特点就是可以动态增减元素。种类有单向链表、双向链表,循环链表。一、单链表单链表的储存思想使用指针表示节点之间的逻辑关系,它的储存单元可以连续也可以不连续,每个储存单元需要储存信息和储存与后继节点的地址信息,储存单元又称之为节点。单链表由头指针唯......
  • 链表(java语言版)
    链表(Linkedlist)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。使用链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域......
  • dremio 25.0 版本的一些问题
    就是最近dremio25.0发布了,昨天在体验了之后似乎一些功能与实际的说明是不太一样的(也可能是社区版的问题)一些问题nessiecatalogga了官方的说法是支持基于api以及ALTERTABLE,ALTERVIEW进行反射更新的,但是似乎是不行的,同时结合源码看就是暂时还支持,只是sql解析支持了......
  • C语言简单的数据结构:单链表的有关算法题(1)
    算法题重点在于思路,代码其实并不难,这里的每一题都提供多种思路,大家可以动手写一下,并找到更好的解题方法这里先介绍前三道题目:1.单链表相关经典算法OJ题1:移除链表元素2.单链表相关经典算法OJ题2:反转链表3.单链表相关经典算法OJ题4:链表的中间结点1.单链表相关经典算......
  • C语言简单的数据结构:单链表
    目录:1.单链表的概念及结构2.单链表的实现2.1单链表的定义、创建和打印2.11单链表的定义2.12单链表的创建2.13单链表的打印2.2单链表的头插和尾插2.21尾插2.22头插2.3单链表的头删和尾删2.31尾删2.31头删2.4单链表的查找2.5单链表指定位置的插入和删除2.51指定位置前......
  • C语言单链表代码实现
    声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。设计算法,实现线性结构上的单链表的产生以及元素的查找、插入与删除,求表长、有序表插入、元素逆置、2个有序表合并等。#include<stdio.h>#include<stdlib.h>//单链表的定义:typedefintDataType......
  • 数据结构:单链表
    一.链表的概念及结构概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。但是在逻辑结构上是顺序的。链表的结构其实就像的火车:车厢是独立存在的,且每节车厢都有车门。想象⼀下这样的场景,假设每节车厢的车门都是锁......
  • CF1250A Berstagram 题解
    题面。题意描述的很清楚,这里就不多赘述。思路看题,对于每个\(a_i\),若\(b_j=a_i\),则将\(b_j\)与\(b_{j-1}\)的值调换(若\(j=1\),则序列不变)。一开始想的是最直接的暴力,复杂度为\(O(nm)\),虽然开了三秒的时限,但\(4\times10^{10}\)的数据明显不是三秒钟就能解决的,含恨倒在第......