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

【每日一题】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. 最后得到一个不含重复绝对值节点的链表。

代码实现

数据结构定义

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

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

算法实现

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

#include"bits/stdc++.h"usingnamespace std;// 链表节点结构structNode{int value; Node* next;};// 去除链表中绝对值相同的节点,仅保留首次出现的节点voidsearch(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 函数对其进行去重操作:

intmain(){ 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;return0;}

代码讲解

  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) 的时间复杂度,更适合大规模链表的数据处理。

总结

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

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

Read more

Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 深度对接企业级 Exchange 服务、实现鸿蒙端邮件与日程的高效分发及 SOAP 协议连接方案

Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 深度对接企业级 Exchange 服务、实现鸿蒙端邮件与日程的高效分发及 SOAP 协议连接方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 ews 的适配 鸿蒙Harmony 实战 - 深度对接企业级 Exchange 服务、实现鸿蒙端邮件与日程的高效分发及 SOAP 协议连接方案 前言 在企业级移动应用的开发版图中,与微软 Exchange Server 的深度集成始终是核心业务需求之一。无论是实时获取会议预约,还是同步企业内部通讯录,Exchange Web Services (EWS) 协议都是那座连接移动端与企业后台的稳健桥梁。 ews 库为 Flutter 提供了工业级的、基于 SOAP 协议的客户端实现。然而,当你试图在鸿蒙系统(OpenHarmony)中拉取成千上万封加密邮件时,如何处理复杂的 XML 解析开销?如何在鸿蒙受限的网络后台准确维持长连接心跳? 适配 ews 到鸿蒙平台,实质上是在进行一场关于“

By Ne0inhk
【Linux:文件 + 进程】进程间通信进阶(1)

【Linux:文件 + 进程】进程间通信进阶(1)

🎬 个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录》 《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》 ⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平 🎬 艾莉丝的简介: 文章目录 * 1 ~> 准备阶段:进程间通信的概念 * 1.1 是什么(本质前提) * 1.2 为什么 * 1.3 怎么办 * 1.4 思维导图 * 2 ~> 进程间通信 * 2.1 进程间通信的定制标准:System V * 2.2 进程间通信的发展 * 3

By Ne0inhk
【Linux】Shell 脚本中的 for 循环语句

【Linux】Shell 脚本中的 for 循环语句

👋 大家好,欢迎来到我的技术博客! 📚 在这里,我会分享学习笔记、实战经验与技术思考,力求用简单的方式讲清楚复杂的问题。 🎯 本文将围绕Linux这个话题展开,希望能为你带来一些启发或实用的参考。 🌱 无论你是刚入门的新手,还是正在进阶的开发者,希望你都能有所收获! 文章目录 * Shell 脚本中的 for 循环语句 🐚🔁 * 什么是 Shell 中的 for 循环?🎯 * 基础语法详解 📚 * 1. 列表式 for 循环 * 2. 使用通配符遍历文件 * 3. C 风格的 for 循环 * 4. 使用 seq 命令生成序列 * 实际应用场景 💼 * 批量文件处理 * 系统监控脚本 * 数据库备份脚本 * 与 Java 的对比 🆚 * 基础 for 循环对比 * 数组遍历对比 * 文件处理对比 * 复杂数据结构处理对比

By Ne0inhk
Flutter 组件 m3u_nullsafe 的适配 鸿蒙Harmony 实战 - 驾驭高安全性流媒体解析、实现鸿蒙端 M3U8 列表动态分屏与直播流审计方案

Flutter 组件 m3u_nullsafe 的适配 鸿蒙Harmony 实战 - 驾驭高安全性流媒体解析、实现鸿蒙端 M3U8 列表动态分屏与直播流审计方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 m3u_nullsafe 的适配 鸿蒙Harmony 实战 - 驾驭高安全性流媒体解析、实现鸿蒙端 M3U8 列表动态分屏与直播流审计方案 前言 在鸿蒙(OpenHarmony)生态的视频监控、在线直播以及短视频应用中,M3U/M3U8 播放列表是支撑起“万物皆流”的核心契约。面对包含数百个切片(Segments)、复杂加密秘钥(Key)以及多码率自适应(Adaptive Bitrate)信息的 M3U 文件,如果缺乏一套健壮的解析引擎,轻则导致画面黑屏,重则因为指针空引用(Null Pointer)导致整个鸿蒙应用崩溃。 在追求极致稳定性的鸿蒙 NEXT 时代,我们需要一种“类型安全”的解析利器。 m3u_

By Ne0inhk