当前位置: 首页 > article >正文

【每日一题】2015考研数据结构 - 求不重复的链表元素

在单链表中存储了 m 个整数,每个节点由两部分组成:[data][link],其中 data 是整数,且满足 |data| < nn 为正整数)。
现要求设计一个高效的算法来处理链表中 data 绝对值相等的节点,只保留首次出现的节点,删除其余绝对值相等的节点。

例如,对于以下链表:

1 -> 2 -> -2 -> 3 -> null

经过处理后,得到的链表为:

1 -> 2 -> 3 -> null

解题思路

本题的关键在于高效去重,即在链表中保留首次出现的数值对应的节点,而删除其他绝对值相等的节点。可以借助 哈希表(unordered_set 来记录已经出现过的节点绝对值。这样,我们可以在遍历链表的同时,实时判断是否存在绝对值重复的节点。

如果你不知道什么是set与实践复杂度的话可参考以下文章

  • C++ 新手指南:如何使用 set 和 unordered_set
  • 【数据结构】时间复杂度和空间复杂度是什么?

具体思路如下:

  1. 从链表头开始遍历,使用一个哈希表 sets 来记录出现过的节点绝对值。
  2. 如果当前节点的绝对值没有出现在 sets 中,则将该节点的绝对值插入 sets,并继续遍历。
  3. 如果当前节点的绝对值已经出现在 sets 中,说明该节点为重复节点,删除该节点并更新链表结构。
  4. 最后得到一个不含重复绝对值节点的链表。

代码实现

数据结构定义

首先定义链表节点的数据结构:

struct Node {
    int value;       // 节点的数值
    Node* next;      // 指向下一个节点的指针
}; 

算法实现

按照上述思路,以下是完整的 C++ 代码实现:

#include "bits/stdc++.h"

using namespace std;

// 链表节点结构
struct Node {
    int value;
    Node* next;
}; 

// 去除链表中绝对值相同的节点,仅保留首次出现的节点
void search(Node* node) {
    unordered_set<int> sets;  // 用于存储出现过的节点绝对值
    Node* prev = node;        // 记录上一个节点

    while(node != nullptr) {
        // 判断当前节点的绝对值是否在哈希集合中
        if(sets.find(abs(node->value)) == sets.end()) {
            sets.insert(abs(node->value));  // 插入当前节点的绝对值
            prev = node;                    // 更新前驱节点
            node = node->next;              // 移动到下一个节点
        } else {
            // 如果绝对值已存在,删除当前节点
            prev->next = node->next;
            Node* n = node;
            node = node->next;
            free(n);  // 释放删除的节点
        }
    }   
}

测试代码

测试代码如下,构建了一个示例链表并调用 search 函数对其进行去重操作:

int main() {
    Node* head = new Node{1, new Node{2, new Node{-2, new Node{3, nullptr}}}};
    
    Node* cur = head;
    cout << "原链表: ";
    while(cur != nullptr) {
        cout << cur->value << " "; 
        cur = cur->next;
    }
    cout << endl;
    
    search(head); 
    
    cur = head;
    cout << "去重后的链表: ";
    while(cur != nullptr) {
        cout << cur->value << " "; 
        cur = cur->next;
    }
    cout << endl;
    
    return 0;
}

代码讲解

  1. 数据结构定义:定义 Node 结构体,包含一个 value 和一个 next 指针,分别表示节点的数值和下一个节点的地址。
  2. 去重逻辑
    • 利用哈希集合 sets 来存储已访问的绝对值。在遍历过程中,检查 sets 中是否存在当前节点的绝对值。
    • 如果不存在,则将绝对值加入集合并继续遍历。
    • 如果存在,则说明当前节点重复,通过调整前驱节点 prev 的指针,跳过该节点并释放其内存。
  3. 时间复杂度:由于哈希表的插入、查找操作平均复杂度为 O(1),因此整体算法的时间复杂度为 O(m),其中 m 是链表的节点个数。
  4. 空间复杂度:由于使用了一个哈希集合来记录绝对值,最坏情况下需要 O(m) 的空间。

复杂度分析

  1. 时间复杂度:遍历链表的复杂度为 O(m),每次检查和插入哈希表的时间复杂度为 O(1),因此总的时间复杂度为 O(m)
  2. 空间复杂度:使用了一个 unordered_set 记录已访问的绝对值,因此空间复杂度为 O(m)

与其他方法的比较

另一种可能的思路是,使用两重循环遍历链表并删除重复节点。但这种方法的时间复杂度为 O(m^2),效率较低。而本算法通过哈希表实现了 O(m) 的时间复杂度,更适合大规模链表的数据处理。

总结

本文介绍了如何在链表中去除绝对值相等的节点,仅保留首次出现的节点,并通过哈希表优化了时间复杂度。在处理去重问题时,哈希表是非常实用的数据结构,可以显著提高算法效率。

通过本题,可以进一步加深对链表操作和哈希表使用的理解,为后续更复杂的数据结构题目打下基础。


http://www.kler.cn/a/385397.html

相关文章:

  • ORACLE创建用户之后查询不到创建的用户
  • _浅谈单片机的gcc优化级别__以双音频信号发生器为例
  • 使用docker方式进行Oracle数据库的物理迁移(helowin/oracle_11g)
  • leetcode20.括号匹配
  • 计算机网络——HTTP篇
  • PyQt5 超详细入门级教程上篇
  • 使用PEFT在多个AMD GPU上进行StarCoder的指令微调
  • 【部署glm4】属性找不到、参数错误问题解决(思路:修改模型包版本)
  • vue之组件网站(后续补)
  • Java基础Day-Fourteen
  • [产品管理-59]:项目组合中产品或项目的类型分类
  • 【电机控制器】STC8H1K芯片——UART串口通信
  • 【K8S系列】K8S 集群 CPU 爆满导致 Pod Pending 状态的分析与解决方案
  • MySQL 到 ClickHouse 数据同步优化(三)
  • Redis3:Hash类型、List类型、Set类型、SortedSet类型
  • Am I Isolated:一款安全态势基准测试工具
  • 【数据集】【YOLO】【目标检测】摔跤识别数据集 5097 张,YOLO行人摔倒识别算法实战训练教程!
  • 自动打电话机器人,好用吗?
  • Trimble X12三维激光扫描仪正在改变游戏规则【上海沪敖3D】
  • UE4/5 编译报错 MSB3073
  • 【Python图像处理】进阶实战指南
  • Spark集群模式搭建之Yarn模式
  • NoETL自动化指标平台为数据分析提质增效,驱动业务决策
  • 域名+服务器+Nginx+宝塔使用SSL证书配置HTTPS
  • 营业执照OCR识别API接口如何用C#调用
  • 系统架构设计师论文:论基于构件的软件开发方法及其应用