LeetCode刷题--- 138. 复制带随机指针的链表(哈希表+迭代)

news2024/11/27 2:46:31

文章目录

  • 一、编程题:430. 扁平化多级双向链表(双指针)
      • 1.题目描述
      • 2.示例1:
      • 3.示例2:
      • 4.示例3:
      • 5.提示:
  • 二、解题思路
      • 1. 题目分析
      • 2. 方法1(哈希表)
        • 思路:
        • 复杂度分析:
        • 算法图解
      • 3. 方法二:迭代
        • 思路:
        • 复杂度分析:
        • 算法图解
  • 三、代码实现
  • 总结


一、编程题:430. 扁平化多级双向链表(双指针)

1.题目描述

  给你一个长度为 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 作为传入参数。LeetCode题目链接。

2.示例1:

在这里插入图片描述

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

3.示例2:

在这里插入图片描述

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]

4.示例3:

在这里插入图片描述

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]

5.提示:

  • 0 <= n <= 1000
  • -104 <= Node.val <= 104
  • Node.random 为 null 或指向链表中的节点。

二、解题思路

1. 题目分析

  这里主要参考了三叶姐和官方题解提供的思路,非常感谢这些大佬。🌹 🌹 🌹
  题目要求我们对一个特殊的链表进行深拷贝。这里就需要注意两点了:

  • 1.在拷贝结束后,不能改变原链表的结构,也是说拷贝过程中可以修改,但结束之后需要还原回去;
  • 2.在拷贝节点时,因为随机指针指向的节点可能还没创建,所以只能先建立拷贝链表,再来完成随机指针的赋值;

2. 方法1(哈希表)

思路:

  • Step 1.将原节点进行复制,在采用哈希表构建原节点和新节点的映射关系;
  • Step 2.对原链表进行遍历,原链表节点上的nextrandom可以通过哈希表查询到对应的新节点,根据其操作给新节点的nextrandom指针进行赋值;
  • Step 3.重复2步骤,直到原链表遍历完时循环终止,并返回新链表头节点;

看不懂解释的话,直接看算法图解比较容易理解点

复杂度分析:

时间复杂度:O(n),其中 n 是链表的长度。对于每个节点,我们至多访问其「后继节点」和「随机指针指向的节点」各一次,均摊每个点至多被访问两次。
空间复杂度:O(n),其中 n 是链表的长度。为哈希表的空间开销。

算法图解

哈希表,红色部分代表新建立节点,灰色部分代表原链表节点;(注:本人不会做成流程动画,希望会的朋友可以私信我指点一二,说个软件名字也可以,谢谢

请添加图片描述

3. 方法二:迭代

  方法一使用哈希表就为了构建原节点和新节点和映射关系,能快速查询每个节点。但也可以不用哈希表进行构建其映射关系;
  在解题过程中我们想要的是原节点和新节点的映射关系,所以将新节点复制在原节点后面,从而构建出其映射关系;

思路:

  • Step 1.对原节点进行复制并将其拼接该节点后面;
  • Step 2.创建好新节点后,可以发现链表中的偶数位置代表原节点,奇数位置代表了新节点(注意:这里是从0开始数起的),每个原节点的next指针都对应着新节点;
  • Step 3.对链表进行遍历,通过计算list[i].random = list[i-1].random.next构建新节点的random指针,其中i为偶数下标,list[i-1]意思是新节点前面的那个原节点;
  • Step 4.重复3步骤,直到原节点遍历完时循环终止,还需要对链表进行拆分再返回新链表头节点;

看不懂解释的话,直接看算法图解比较容易理解点

复杂度分析:

时间复杂度:O(n),其中 n 是链表的长度。我们只需要遍历该链表三次。
空间复杂度:O(1)。注意返回值不计入空间复杂度。

算法图解

  红色部分代表原节点,灰色部分代表新节点,蓝色部分为当前遍历的节点;(注:本人不会做成流程动画,希望会的朋友可以私信我指点一二,说个软件名字也可以,谢谢

  • 复制新节点

请添加图片描述

  • 构建新节点random关系

请添加图片描述

  • 拆分链表

请添加图片描述


三、代码实现

每个代码块都写了注释,方便理解,代码还可以改进;

方法一:哈希表

class Solution {
    public Node copyRandomList(Node head) {
        HashMap<Node, Node> map = new HashMap<>();
        Node p = head, q;
        while(p != null){
            q = new Node(p.val);
            map.put(p,q);
            p = p.next;
        }

        p = head;
        q = map.get(p);
        // 通过散列表特性加快查询速度
        while(p != null){
            q.next = map.get(p.next);
            q.random = map.get(p.random);
            q = q.next;
            p = p.next;
        }

        return map.get(head);
    }
}

提交结果:
在这里插入图片描述

方法二:迭代

class Solution {
    public Node copyRandomList(Node head) {
        if (head == null) return head;
        Node first = head, temp;

        // 复制链表,将当前节点复制在节点后面
        while(first != null){
            temp = new Node(first.val);
            temp.next = first.next;
            first.next = temp;
            first = temp.next;
        }

        // 构建节点random关系
        first = head;
        while(first != null){
            if(first.random != null) first.next.random = first.random.next;
            first = first.next.next;
        }

        // 拆分链表
        first = head;
        Node second = head.next;
        while(first != null){
            Node temp_second = first.next;
            if(temp_second != null) first.next = temp_second.next;
            first = temp_second;
        }

        return second;
    }
}

提交结果:

在这里插入图片描述


总结

以上就是今天要讲的内容,这一题还是比较容易被题意误导的,一开始我就改变了原链表的结构导致出错,后面看了各位大佬的题解就突然恍然大悟了。

感谢观看,如果有帮助到你,请给题解点个赞和收藏,让更多的人看到。🌹 🌹 🌹

也欢迎你,关注我。👍 👍 👍

你们的点赞和留言对我真的很重要!!!😄 😄 😄

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

备考 PMP 考试时需要着重注意什么?

PMP考试难度并不是很大。科学备考一定没有问题的&#xff5e;这里在和大家说说2023年PMP的考试时间&#xff1a;3月、5月、8月、11月&#xff08;其中3月不开启新报名&#xff09;需要注意的地方还是蛮多的。我就根据自己考试的经验和大家分享一下在考试整个过程中注意啥&#…

2023年广西最新建筑施工焊工(建筑特种作业)模拟试题及答案

百分百题库提供特种工&#xff08;焊工&#xff09;考试试题、特种工&#xff08;焊工&#xff09;考试预测题、特种工&#xff08;焊工&#xff09;考试真题、特种工&#xff08;焊工&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻…

【nodejs】nodejs入门核心知识(命令行使用、内置模块、node 模块化开发)

&#x1f4bb; nodejs入门核心知识(命令行使用、内置模块、node 模块化开发) &#x1f3e0;专栏&#xff1a;JavaScript &#x1f440;个人主页&#xff1a;繁星学编程&#x1f341; &#x1f9d1;个人简介&#xff1a;一个不断提高自我的平凡人&#x1f680; &#x1f50a;分享…

(1分钟突击面试) 高斯牛顿、LM、Dogleg后端优化算法

高斯牛顿法 LM法 DogLeg方法编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;知识点&#xff1a;高斯牛顿是线搜索方法 LM方法是信赖域方法。编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;这个就是JTJ是…

React设计原理—1框架原理

阅读前须知 本文是笔者学习卡颂的《React设计原理》的读书笔记&#xff0c;对书中有价值内容以Q&A方式进行呈现&#xff0c;同时结合了自己的理解&#x1f914;阅读时推荐先看问题&#xff0c;想想自己的答案&#xff0c;再和答案比对一下本文属于前端框架科普&#xff0c;…

68. Python的相对路径

68. Python的相对路径 文章目录68. Python的相对路径1. 知识回顾2. 什么是相对路径3. 相对路径的语法4. 查看相对路径的方法5. 写出所有txt文件的相对路径5.1 同目录5.2 上级目录6. 用相对路径读取txt文件6.1 读取旅游.txt6.2 读取旅游经费.txt6.3 读取笔记.txt和new.txt6.4 读…

微服务调用组件Feign

目录 JAVA 项目中如何实现接口调用&#xff1f; Httpclient Okhttp HttpURLConnection RestTemplate WebClient 什么是Feign 优势 Spring Cloud Alibaba快速整合OpenFeign 引入依赖 编写调用接口FeignClient注解 调用端在启动类上添加EnableFeignClients注解 发起调…

【送书活动】学Vue核心技术和uni-app跨平台实战项目就来看看这本书

本节目录1、书籍介绍2、推荐理由2.1 有充足的配套资源图书页内展示。2.2 PPT示例代码讲解演示2.3 内容由浅入深&#xff0c;渐进式学习3、参与方式1、书籍介绍 本书共分为14个章节&#xff0c;包括Vue.js核心基础、Vue.js高级进阶、Axios发送HTTP请求&#xff0c;Vuex状态管理…

牛客 面试必刷TOP101 题解(3、二叉树)

23 二叉树的前序遍历 /*** struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* };*/ #include <vector> class Solution { public:vector<int> ans;void show(TreeNode…

腾讯架构师极力推荐:Java多线程与Socket实战微服务框架

在这个技术不断更新的年代&#xff0c;跟不上时代变化的速度就会被刷掉&#xff0c;特别是咱们程序员这一群体&#xff0c;技术不断更新的同时也要同时进步&#xff0c;不然长江后浪推前浪&#xff0c;前浪… 一个程序员从一个什么都不懂的小白在学到有一定的Java基础的时候肯…

WebDAV之葫芦儿·派盘+可达漫画

可达漫画 支持WebDAV方式连接葫芦儿派盘。 这是一款专为阅读你的漫画收藏而设计的阅读器。 热爱漫画的你肯定收藏了不少各种类型的漫画,它们可能有各种各样的格式,zip,rar,cbz,cbr,epub, mobi 或 pdf,也可能只是单纯的文件夹。 可达漫画支持「流式阅读」

数据推荐 | 手势识别训练数据集

多样化&#xff0c;有按键、语音等&#xff0c;也由于整个疫情的大环境下&#xff0c;一种更方便更卫生更符合人们的非接触式交互方式—手势识别正大步发展&#xff0c;极富图像化和具备行动性的手势操作将会与人们的生活息息相关。 手势识别应用场景广泛&#xff0c;常见应用…

【微电网】并网微电网运行经济性研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

面试官问我:说说你对JMM内存模型的理解?为什么需要JMM?

点个关注&#xff0c;必回关 随着CPU和内存的发展速度差异的问题&#xff0c;导致CPU的速度远快于内存&#xff0c;所以现在的CPU加入了高速 缓存&#xff0c;高速缓存一般可以分为L1、L2、L3三级缓存。基于上面的例子我们知道了这导致了缓存一致 性的问题&#xff0c;所以加入…

字符串常量池

1.创建对象的思考下面两种创建字符串的方式一样吗&#xff1f;public static void main(String[] args) {//两者一样吗String s1 "hello";String s2 "hello";String s3 new String("hello");String s4 new String("hello");System…

11 Advanced CNN

文章目录GoogLeNetInception Module1x1 Conv计算效果代码实现总结ResNet (残差网络)问题引入梯度消失与传统神经网络的比较代码实现课程来源&#xff1a; 链接对于前篇中所提到问题&#xff0c;设计出的是一种类似于LeNet5的线性结构&#xff0c;而对于大多数问题&#xff0c;简…

postgresql 数据库小版本更新

postgresql 数据库小版本更新 记录一次pg小版本更新 文章目录postgresql 数据库小版本更新前言一.下载最新的pg版本 pg11&#xff08;11.18&#xff09;二 pg11.5 升级 pg11.18过程1. 查看当前数据库版本&#xff1a;2. 关闭pg11.5数据库3. 安装pg11.184.修改 配置文件5. 重新…

【yolov5】yolov5训练自己的数据集全流程----包含本人设计的快速数据处理脚本

关于yolo应用时能用到的脚本集合&#xff0c;推荐收藏&#xff1a; https://chenlinwei.blog.csdn.net/article/details/127299428 1. 工程化快速yolo训练流程指定版&#xff08;无讲解&#xff09; 1.1 抽样数据集xml转txt输出量化分析 python make_dataset.pymake_dataset…

Little Fighter:旺角——NFT 系列来袭!

《小朋友齐打交 2 (LF2) 》是一款流行的格斗游戏&#xff0c;由 Marti Wong 和 Starsky Wong 于 1999 年创作。这是一款非常容易上瘾的游戏&#xff0c;具有多种游戏模式、横向卷轴格斗系统以及 24 个具有复杂动作和连击的不同角色。这款游戏在世界范围内非常受欢迎&#xff0c…

Debain安装命令

目录 一、安装sudo命令 二、安装jdk8 三、更换软件源 四、Debian 安装 yum 五、安装zip、unzip、curl、lrzsz、NUMA 六、安装Maven 五、问题 一、安装sudo命令 1&#xff09;执行sudo命令&#xff0c;提示 -bash: sudo: command not found的解决方法 apt-get install s…