【面试经典150 | 链表】随机链表的复制

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:哈希表+递归
    • 方法二:哈希表
    • 方法三:迭代+拆分节点
  • 写在最后

Tag

【递归】【迭代】【链表】


题目来源

138. 随机链表的复制


题目解读

对一个带有随机指向的链表进行深拷贝操作。


解题思路

本题一共有三种解法,分别是:

  • 哈希表+递归;
  • 哈希表;
  • 迭代+节点拆分。

前两种方法都需要用到哈希表这种基本的数据结构,哈希表中存放的数据都是源节点与深拷贝后的节点这样的键值对,但是一个(方法一)是使用递归进行完成深拷贝任务,而另一个(方法二)使用迭代来完成深拷贝工作,这两种方法属于常规解法了。

第三种解法比较巧妙,省去了哈希表,节省了空间,面试的时候能够清晰的答出该方法一定可以令面试官眼前一亮。

接下来具体看一看这三种解法。

方法一:哈希表+递归

如果是对一个普通的链表进行深拷贝操作,我们直接按照遍历的顺序创建链表即可。但是,本题中的链表有一个随机指针,指向链表中的随机的一个节点,如果还是按照链表顺序拷贝节点,当前拷贝的节点的随机节点可能还没有创建。

于是会有两种不同的思路,一是通过递归的方法创建需要的节点,具体地:

  • 维护一个哈希表 cacheNode 用来存放源节点与深拷贝后的节点;
  • 首先创建头结点的拷贝节点,并存入到哈希表中;
  • 接着递归建立新头结点的下一个节点与随机节点,也就是调用自身;
  • 最后返回 cacheNode[head]

实现代码

/*
// Definition for a Node.
class Node {
public:int val;Node* next;Node* random;Node(int _val) {val = _val;next = NULL;random = NULL;}
};
*/class Solution {
public:unordered_map<Node*, Node*> cacheNode;Node* copyRandomList(Node* head) {if (head == NULL) {return NULL;}    if (!cacheNode.count(head)) {Node* newHead = new Node(head->val);cacheNode[head] = newHead;newHead->next = copyRandomList(head->next);newHead->random = copyRandomList(head->random);}return cacheNode[head];}
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n) n n n 是链表的长度。

空间复杂度: O ( n ) O(n) O(n)


方法二:哈希表

直接使用根据每个节点拷贝出新的节点,存放到哈希表中,然后根据原链表的指向关系更新新节点的指向关系。

实现代码

/*
// Definition for a Node.
class Node {
public:int val;Node* next;Node* random;Node(int _val) {val = _val;next = NULL;random = NULL;}
};
*/class Solution {
public:unordered_map<Node*, Node*> cacheNode;Node* copyRandomList(Node* head) {if (head == NULL) {return NULL;}    Node* curr = head;while (curr != NULL) {cacheNode[curr] = new Node(curr->val);curr = curr->next;}curr = head;while (curr != NULL) {cacheNode[curr]->next = cacheNode[curr->next];cacheNode[curr]->random = cacheNode[curr->random];curr = curr->next;}return cacheNode[head];}
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n) n n n 是链表的长度。

空间复杂度: O ( n ) O(n) O(n)

方法三:迭代+拆分节点

方法三和方法二类似,都是先将原链表拷贝一次,只是本方法是先将拷贝后的链表先连在原链表后,接着就是巧妙的连接与拆分方法,接下来以图示的方式进行分析:

原链表为 A->B->C

深拷贝节点并连接next指针

我们先在原链表的节点之后深拷贝一个新的节点并连接,生成一个新的链表 A->A'->B->B'->C->C'。实现的方法与在链表指定节点 node 之后插入一个新的节点类似:

  • 先深拷贝节点 node 得到新的节点 newNode
  • 再将拷贝得到的新节点 newNode 连接到 node->next
  • 最后将 node 连接到 newNode

连接random指针

现在需要解决拷贝后的链表的 random 指针指向问题,node 的下一个节点就是 newNodenewNoderandom 指针指向就是 noderandom 指向,我们就根据 node 来更新就可以。具体实现见代码。

切断两链表之间的联系

解决好 random 指针指向问题,就要切断两个链表之间的联系。具体实现见代码

实现代码

/*
// Definition for a Node.
class Node {
public:int val;Node* next;Node* random;Node(int _val) {val = _val;next = NULL;random = NULL;}
};
*/class Solution {
public:Node* copyRandomList(Node* head) {if (head == NULL) {return head;}// 深拷贝节点并连接next指针for (Node* node = head; node != NULL; node = node->next->next) {Node* newNode = new Node(node->val);newNode->next = node->next;node->next = newNode;}// 连接random指针for (Node* node = head; node != NULL; node = node->next->next) {Node* newNode = node->next;newNode->random = (node->random != NULL) ? node->random->next : NULL;}// 切断两链表之间的联系Node* newHead = head->next;for (Node* node = head; node != NULL; node = node->next) {Node* newNode = node->next;node->next = node->next->next;newNode->next = (newNode->next != NULL) ? newNode->next->next : NULL;}        return newHead;}
};

时间复杂度: O ( n ) O(n) O(n) n n n 是链表的长度。

空间复杂度: O ( 1 ) O(1) O(1),答案链表不算作额外的空间。


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

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

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

相关文章

【Linux】配置JDKTomcat开发环境及MySQL安装和后端项目部署

目录 一. JDK及tomcat安装 二&#xff0c;安装Tomcat 三&#xff0c;MySQL安装 四、后端部署 前言&#xff1a; 今天我们就来在Linux上安装JDK及tomcat&#xff0c;MySQL&#xff0c;希望你可以通过这一博客&#xff0c;找到你的答案&#xff01;&#xff01;&#xff01; …

基于Apache SeaTunnel 的数据精确一致性技术实践

引言 在分布式系统中&#xff0c;保障数据一致性是至关重要的任务之一。数据一致性是指分布式系统中的各个节点在进行数据更新时能够保持数据的准确性和完整性。然而&#xff0c;由于网络延迟、节点故障等原因&#xff0c;分布式系统中的数据一致性问题变得复杂而具有挑战性。…

Windows环境下使用VLC获取到大疆无人机的RTMP直播推流

1.环境准备 1.安装nginx 1.7.11.3 Gryphon 下载地址&#xff1a;http://nginx-win.ecsds.eu/download/ 下载nginx 1.7.11.3 Gryphon.zip&#xff0c;解压后修改文件夹名称为nginx-1.7.11.3-Gryphon&#xff1b; 2.安装nginx-rtmp-module 下载地址&#xff1a;GitHub - arut…

7+单细胞分析+预后模型构建+验证实验思路,干湿结合也能拿高分

今天给同学们分享一篇单细胞分析肿瘤预后模型构建验证实验思路的生信文章“Identification of a novel immune-related gene signature for prognosis and the tumor microenvironment in patients with uveal melanoma combining single-cell and bulk sequencing data”&…

土壤数据库辅助工具SPAW计算土壤导水率

土壤数据库辅助工具SPAW 首先下载SPAW工具 点击打开 根据之前的1比100土壤数据查表得到各个组分含量 其中 Field Capacity是田间持水量 Matric Bulk Density是基质粒密度 参考文章 【SWAT水文模型】ArcSWAT土壤数据库辅助工具SPAW简述

苹果相机怎么磨皮 苹果手机怎么磨皮

相信使用苹果相机的小伙伴都有这样的疑惑&#xff0c;苹果相机怎么磨皮&#xff1f;其实可以通过相机的参数进行设置从而达到磨皮的效果&#xff0c;如果觉得相机自带的设置磨皮效果不够好&#xff0c;可以下载磨皮软件来对照片磨皮。今天的文章就来给大家介绍苹果相机怎么磨皮…

问题 D: 免费馅饼(类数塔问题)

免费馅饼 都说天上不会掉馅饼&#xff0c;但有一天gameboy正走在回家的小径上&#xff0c;忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了&#xff0c;这馅饼别处都不掉&#xff0c;就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了&#xff0c;所以…

windows docker desktop 更换镜像 加速

最近 docker hub 访问不了; 经过研究 可以通过添加 代理镜像网址 添加代理服务器的方式 实现完美访问 1添加镜像网站 修改成国内镜像地址就能享受到飞一般的速度&#xff0c;但有一个问题&#xff0c;部分站点镜像不全或者镜像比较老&#xff0c;建议使用多个镜像站。 https…

【Verilog】7.2.1 Verilog 并行 FIR 滤波器设计

FIR&#xff08;Finite Impulse Response&#xff09;滤波器是一种有限长单位冲激响应滤波器&#xff0c;又称为非递归型滤波器。 FIR 滤波器具有严格的线性相频特性&#xff0c;同时其单位响应是有限长的&#xff0c;因而是稳定的系统&#xff0c;在数字通信、图像处理等领域…

私有网络的安全保障,WorkPlus Meet内网视频会议助力企业高效会议

在企业内部沟通与协作中&#xff0c;视频会议成为了一种必不可少的沟通方式。然而&#xff0c;传统的互联网视频会议往往受制于网络不稳定因素&#xff0c;给企业带来不便与困扰。WorkPlus Meet作为一款专注内网视频会议的软件&#xff0c;致力于为企业打造高效、稳定的内网视频…

使用NVIDIA GPU FFmpeg转码 YUV to H264(成功)

0. 官方教程 NVIDIA官方教程&#xff1a;链接&#xff0c;本篇内容主要参考2.2 Software Setup。 1. 安装显卡驱动 确保nvidia-smi能够正常使用&#xff1a; 2. 安装CUDA toolkit 注意要与显卡驱动版本对应&#xff0c;验证toolkit是否正确安装&#xff1a; 3. 安装ffnvco…

有多个网站的话申请什么样的SSL证书比较好?

在当今互联网时代&#xff0c;许多组织和个人都需要同时管理多个网站&#xff0c;这可能包括公司内部网站、在线商店、博客等。为了确保这些网站的安全性和数据保护&#xff0c;选择适合管理多个网站的SSL证书至关重要。今天小编就为大家详细介绍下&#xff0c;不同情况下多个网…