力扣 138. 随机链表的复制

题目描述:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。

你的代码  接受原链表的头节点 head 作为传入参数。

思路:

题目要求我们拷贝一个带next指针与random随机访问指针的链表。

如果拷贝一个只带next指针的链表话呢,很简单,根据next依次遍历目标链表,再依次拷贝每个节点的信息就可以了.

一步一步来,我们可以先根据next“这条线” 先拷贝一个新的链表出来。

为什么不是优先根据random指针来拷贝呢?

这是因为random指针指向的是随机节点,可能有环存在,而且,random指向的节点有可能是很后面才出现的节点,而next在题目给出节点目标信息时关系就确定是线性不成环的,所以我们优先考虑拷贝next联系。

 如何拷贝各个节点的random联系呢?--本题重点

首先,我们假设每一个random关系是一条有向边,在旧链表中存在random关系(A)-->(B),

那么对应的,我们想让复制出来的新链表也有这么一条边,且为(a)-->(b)

那么如果我们能通过(A)找到(a),通过(B)找到(b),在遍历旧链表的random关系链中,我们就能顺便建立复制体的关系。(其中节点a是A的复制节点,b是B的复制节点)

也就是说,只要我们能通过某种联系找到自己的复制体,那么我们就能复制random联系。

于是题目的关键转移到了如何将这种联系该存下来且能快速找到呢?

根据哈希思想给出以下解法:

解法一:

如果是c++的话,可以用STL库中的map容器来存下旧链节点在新链的复制体节点。

也就是达到hash[A]=a,hash[B]=b.

unordered_map<Node *, Node *> Hash({{NULL, NULL},{head, newhead}});

我这里照顾只学了c语言的朋友,主要讲方法二,不用map容器。

解法二:

改变旧链表的next,使其在被复制完后指向对应的复制体节点。

这里说的复制完是指复制val信息,以及next联系.

在复制next信息时,假设遍历到了A节点,首先用一个临时遍历temp存放A->next。

当我们创造出来了复制体a节点,我们让A->next=a,然后,a->random=A->random.

在将temp里的节点取出来继续遍历。

为什么要 a->random=A->random?

这是因为由于我们已经破坏了目标链表的next关系,我们之后再想复制random关系就不能再遍历旧链表了,仅依靠random关系可能出现环等问题,所以要想复制random关系,我们就要遍历新链表,也就是刚被复制出来的不完全体。

遍历到当前节点a,我们想要找a 的random应该指向哪里,我们可以先找到A的random指向的B,再通过B->next找到b,又因为A的random终点已经被赋给了a->random,所以就有了最重要的一步:

a->random=a->random->next.

这里a->random->next就是指向b节点。

重复以上步骤,就可以将所有random关系复制下来。

解法三:

思路和方法二差不多,只不过是将a->next=A -->next  然后A->next=a.这样一来,在破坏旧链的next关系后我们通过依旧可以通过A->next->next找到原来A的下一个节点。

这样我们再将a->random=A->random->next(先在目标链中找到B,再通过B->next找到b).

这个方法只不过是恢复了旧链的可遍历性而已,和方法二差不多。

代码:

#define _CRT_SECURE_NO_WARNINGS 1struct Node* copyRandomList(struct Node* head) {if (head == NULL)return NULL;struct Node* phead = head;struct Node* newhead = (struct Node*)malloc(sizeof(struct Node));//新链的头指针struct Node* np = newhead;struct Node* star = newhead;while (phead) {struct Node* t = phead->next;//临时变量,存放phead的下一个节点,防止丢失newhead->val = phead->val;newhead->random = phead->random;//为了方便后续建立random联系phead->next = newhead;//哈希的思想,建立新、旧两个节点的联系if (t == NULL) {//如果下一个节点是NULL,就不用开辟空间了newhead->next = NULL;}else {//否则就创造一个节点空间,建立next关系newhead->next = (struct Node*)malloc(sizeof(struct Node));newhead = newhead->next;}phead = t;}while (np != NULL) {if (np->random != NULL) {np->random = np->random->next;//通过旧链找到新链应该指向的节点}np = np->next;}return star;}

总结:

这个题总的来说不难,如果想用c写出来的话就要求对链表比较熟悉,还是比较考验基本功滴!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/183305.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

newstarctf2022week2

Word-For-You(2 Gen) 和week1 的界面一样不过当时我写题的时候出了个小插曲 连接 MySQL 失败: Access denied for user rootlocalhost 这句话印在了背景&#xff0c;后来再进就没了&#xff0c;我猜测是报错注入 想办法传参 可以看到一个name2,试着传参 发现有回显三个字段…

ESP-IDF-V5.1.1使用websocket

IDF Component Registry (espressif.com) 在windows系统中&#xff0c;在项目目录下使用命令 idf.py add-dependency "espressif/esp_websocket_client^1.1.0"

【手册上新】迅为RK3588开发板多屏显示手册

iTOP-RK3588开发板采用四核Cortex-A76处理器和Cortex-A55架构&#xff0c;芯片内置VOP控制器&#xff0c;最多可以支持7个屏幕显示&#xff0c;支持HDMI、LVDS、MIPI、EDP四种显示接口的多屏同显、异显和异触&#xff0c;可有效提高行业定制的拓展性。 iTOP-RK3588开发板支持以…

Java中访问修饰符

类和类之间的关系有如下几种: 以Hero为例自身&#xff1a;指的是Hero自己同包子类&#xff1a;ADHero这个类是Hero的子类&#xff0c;并且和Hero处于同一个包下不同包子类&#xff1a;Support这个类是Hero的子类&#xff0c;但是在另一个包下同包类&#xff1a; GiantDragon 这…

EasyExcel实现动态表头功能

EasyExcel实现动态表头功能 开发过程中&#xff0c;大部分都会使用到导出报表功能&#xff0c;目前阶段会用得有 poi导出&#xff08;暂无&#xff09;&#xff0c; easyexcel导出&#xff08;官方文档&#xff0c;https://easyexcel.opensource.alibaba.com/docs/current/&am…

Linux 实现原理 — NUMA 多核架构中的多线程调度开销与性能优化

前言 NOTE&#xff1a;本文中所指 “线程” 均为可执行调度单元 Kernel Thread。 NUMA 体系结构 NUMA&#xff08;Non-Uniform Memory Access&#xff0c;非一致性存储器访问&#xff09;的设计理念是将 CPU 和 Main Memory 进行分区自治&#xff08;Local NUMA node&#x…

EPLAN-P8软件技术分享文章

EPLAN公司成立于1984年德国。EPLAN最初的产品是基于DOS平台&#xff0c;然后经历了Windows3.1、Windows95、Windows98、Windows2000、Windows Vista等、Windows7、Windows8等平台发展历史。EPLAN是以电气设计为基础的跨专业的设计平台&#xff0c;包括电气设计、流体设计、仪表…

06-MySQL-进阶-视图存储函数存储过程触发器

涉及资料 链接&#xff1a;https://pan.baidu.com/s/1M1oXN_pH3RGADx90ZFbfLQ?pwdCoke 提取码&#xff1a;Coke 一、视图 数据准备 create table student(id int auto_increment comment 主键ID primary key,name varchar(10) null comment 姓名,no varchar(10) null co…

vue3的自定义指令

除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (CustomDirectives)。 1.自定义指令的目的和简单介绍 自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。 一个自定义指令由一个包含类似组件生命周期钩子的对象…

【网络安全 --- web服务器解析漏洞】IIS,Apache,Nginx中间件常见解析漏洞

一&#xff0c;工具及环境准备 以下都是超详细保姆级安装教程&#xff0c;缺什么安装什么即可&#xff08;提供镜像工具资源&#xff09; 1-1 VMware 16.0 安装 【网络安全 --- 工具安装】VMware 16.0 详细安装过程&#xff08;提供资源&#xff09;-CSDN博客文章浏览阅读20…

Modbus入门

Modbus入门 ModbusModbus模拟工具模拟工具使用配置Slave配置Poll C#使用ModBus通讯 Modbus modbus使用范围广泛&#xff0c;广泛应用于各类仪表&#xff0c;PLC等。它属于应用层协议&#xff0c;底层硬件基于485/以太网。 Modbus的存储区有&#xff1a;输入线圈&#xff08;布尔…

有什么软件可以管控员工的电脑桌面

信息化的快速发展&#xff0c;员工在工作中使用电脑的情况越来越普遍。然而&#xff0c;员工在使用电脑时可能会出现工作效率低下、滥用公司资源等问题&#xff0c;因此对员工电脑进行监测和管理显得尤为重要。 1、域之盾软件 它是一款功能强大的电脑监控软件&#xff0c;可以…

分享98个节日庆典PPT,总有一款适合您

分享98个节日庆典PPT&#xff0c;总有一款适合您 PPT下载链接&#xff1a;https://pan.baidu.com/s/1gNj_uRLz9a5uTG97ezma7Q?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易。知识付…

【Solidity】Remix在线环境及钱包申请

好久没有学习区块链方面的知识了&#xff0c;目前通过自学大致掌握了Fabric联盟链的搭建&#xff0c;链码编写、部署&#xff0c;api调用&#xff0c;可以独立开发出一些基于fabric的应用&#xff0c;感觉开发出去中心化的应用还是很有意思的&#xff0c;因为他与之前开发的ssm…

mysql主从架构

mysql主从架构是一套非常基础的高可用架构&#xff0c;主要依赖复制技术来实现。 1.复制原理 mysql复制功能主要使用三个线程实现&#xff1a; 1.Binary log dump thread&#xff08;二进制日志转储线程&#xff09;:当副本连接时发送二进制日志 2.Replication I/O receiver …

Docker与微服务实战——基础篇

Docker与微服务实战——基础篇 第一章 Docker 简介1.1 docker 理念1.2 容器与虚拟机比较 第二章 Docker 安装2.1 前提说明2.2 Docker的基本组成2.2.1 镜像&#xff08;image&#xff09;2.2.2 容器&#xff08;container&#xff09;2.2.3 仓库&#xff08;repository&#xff…

如何使用Node.js快速创建HTTP服务器并实现公网访问本地Server

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

Spark 基础知识点

Spark 基础 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 什么是Spark 什么是Spark 1.1 定义&#xff1a;Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎 Spark最早源于一篇论文 Re…

51单片机-串口通信

文章目录 前言1.基础介绍2.串口实战3.4. 前言 1.基础介绍 常见1&#xff0c;2&#xff0c;3,电源 常用方式1 fosc外部晶振 2.串口实战 3. 4.

AI:57-基于机器学习的番茄叶部病害图像识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌在这个漫长的过程,中途遇到了不少问题,但是…