【LeetCode】138. 复制带随机指针的链表

news2025/1/21 12:49:06

题目链接:https://leetcode.cn/problems/copy-list-with-random-pointer/description/

📕题目要求:

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


 🧠解题思路 

方案一:单独将复制的结点组合为复制链表

该方案是效率比较低的一种,也是大家能够最容易想到的一种方法。第一次遍历原链表,同时每次迭代时申请一个新结点,复制原链表结点的信息(val)给新结点,再将结点进行连接迭代,组成链表。第二次迭代,也是该题最关键的一步,确定random的指向,通过原链表random指向的相对位置进行类比推理,最终确定指向。

时间复杂度为:O(N^2) 

方案二:单链表的插入操作大幅减少时间复杂度

将原结点与拷贝结点建立出某种关系(拷贝结点插在了在原结点后),通过插入操作将拷贝结点插入到原结点之后。然后遍历控制random的指向。

时间复杂度为:O(N) 


🍭代码示例

玩法一代码示例如下:

struct Node* copyRandomList(struct Node* head) 
{
    if(head==NULL)
    {
        return head;
    }
   struct Node* newhead = NULL;
   struct Node* cur = NULL;
   struct Node* next = head;
   if(newhead==NULL)
   {
        struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
        newnode->next = NULL;
        newnode->random = NULL;
        cur = newhead = newnode;
        cur->val = next->val;
        next = next->next;
   }
    while(next)
    {
        struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));
        newnode->next = NULL;
        newnode->random = NULL;
        cur->next = newnode;
        cur = cur->next;
        cur->val = next->val;
        next = next->next;
   }
   cur = newhead;
   next = head;
   while(next)
   { 
        int k = 0;
        struct Node* mov1 = head;
        struct Node* mov2 = newhead;
        if(next->random==NULL)
        {
            cur->random=NULL;
        }
        else
        {
            while(mov1!=next->random)
            {
                mov1 = mov1->next;
                k++;
            }
            while(k--)
            {
                mov2 = mov2->next;
            }
            cur->random = mov2;
        }
        next = next->next;
        cur = cur->next;
   }
   return newhead;
}

玩法二代码示例如下:

struct Node* copyRandomList(struct Node* head) 
{
    struct Node* cur = head;
	//1.对拷贝链表与原链表建立关系:拷贝节点插入到原结点的后面
    while(cur)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        
        struct Node* next = cur->next;
        copy->val = cur->val;
        //插入
        cur->next = copy;
        copy->next = next;
        //迭代
        cur = next;
    }
    //2.控制拷贝结点的random
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        if(cur->random==NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }
        //迭代
        cur = copy->next;
    }
    //将拷贝结点解下尾插组成拷贝链表,并恢复原链表。
    struct Node* copyHead = NULL;
    struct Node* copyTail = NULL;
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;

        if(copyTail == NULL)
        {
            copyHead = copyTail = copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail = copyTail->next;
        }
        cur->next = next;
        cur = next;
    }
    return copyHead;
}

这就是我对本题的理解,如果大家有更优的解,欢迎交流,一起进步! 

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

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

相关文章

基于springboot+mybatis-puls+mysql+html实现大学生创新创业管理系统

基于springbootmybatis-pulsmysqlhtml实现大学生创新创业管理系统 一、系统介绍1、系统主要功能:2.涉及技术框架:3.本项目所用环境: 二、功能展示三、其它系统四、获取源码 一、系统介绍 1、系统主要功能: 学生:申报…

自更新参数web接口预热工具

痛点 日常上线流程中经常需要对接口进行预热,因为服务器每次启动后都有一定次数访问失败,如果不处理将此请求直接抛出,会降低用户体验。当服务器数量较少时,我们可以在发布机器后,待机器启动使用本地hosts更改IP&…

20230510MTCNN3

MTCNN数据制作 - 1 多任务 分类任务 回归任务 模型增加任务,其实就是增加输出 级联即减少了 数据量,又增加了 模型的精度 级联可以让网络变得越快 越好 单独来看这三个网络,它们的效果不会好,因为网络太浅了 但,当…

【嵌入式烧录刷写文件】-1.3-删除/修改Motorola S-record(S19/SREC/mot/SX)文件中指定地址范围内的数据

案例背景(共6页精讲): 有如下一段S19文件,如何“自动”地完成地址范围0x9110-0x9113数据的删除或修改。 S0110000486578766965772056312E30352EA6 S123910058595A5B5C5D5E5F606162636465666768696A6B6C6D6E6F70717273747576775B…

t检验前世今生

1、背景 t检验是科研中非常常用的一种方法和手段,但是理解到位的人并不多,虽然这也不影响其使用。本文主要目的在于将与t检验有关的前前后后都讲明白。 2、补充知识 理解t检验,我们需要补充一些统计学有关的先验知识。 2.1 正态分布 概率…

【文本三剑客】SED

SED 一、sed编辑器1.2sed简介1.3sed工作流程1.4sed命令格式1.5常用选项1.6常用操作 二、sed实验2.1打印内容2.2删除行2.3替换2.4插入 一、sed编辑器 1.2sed简介 sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。sed编辑器可…

链表详解 - C语言描述

目录 认识链表 链表的分类 链表的实现 单链表的增删查改 增操作 删操作 查操作 改操作 带头双向循环链表 认识链表 链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。链表由一系列节点(结点)组…

最火爆ChatGPT知识星球分享,开启与GPT的神奇之旅

今天给大家介绍的是一个讲解ChatGPt的知识星球,这个星球是专门为ChatGPT爱好者和AI绘画感兴趣的朋友们打造的。这个知识星球主题是关于ChatGPT的,旨在提供一个交流、学习和探索GPT的平台。 这里有一个强大的阵容,汇集了许多对人工智能和自然…

.Net平台下OpenGL绘制图形(2)(VS2019,Winform,C#)

本节主要讲诉图形绘制的原理,使用介绍和代码演示。 原理介绍 我们先来讲讲OpenGL的图形绘制。其实,所有的图形都是由许多个小图形连接而成的。你可以理解为是图片的像素,一张彩图是由很多个色彩不一的像素点组合而成。要实现色彩绚丽的图形设…

安装旧版本chrome 浏览器方法

1、下载 国内推荐下载网址:https://www.slimjet.com/chrome/google-chrome-old-version.php 我自己目前再用的103.0.5060.53版本,也可以到我网盘下载[若失效可联系我更新]。 2、安装之前,请先卸载干净当前版本 打开控制面板,找打…

挣值管理专题

挣值管理 基本思路 该方法的基本思想是应用统计学的原理,通过引进一个中间变量即“挣值”来帮助项目管理者分析项目成本的变动情况,并给出项目成本与工期相关变化的信息及对项目成本发展趋势作出预测与决策。 挣值的定义 挣值是一个表示项目“已完成作业…

Linux多路复用机制原理分析--select/poll

前言 Linux访问设备的IO模型主要有五种,分别是非阻塞IO模型、阻塞IO模型、IO多路复用模型、信号驱动模型以及异步IO模型。本文主要分析IO多路复用模型,Linux下的IO多路复用模型主要有select/poll/epoll等机制实现。 IO多路复用模型可以实现以非阻塞的方…

Dijkstra算法图解,C++实现Dijkstra算法

目录 Dijkstra算法简介数据结构抽象初始化开始计算第一轮计算第二轮计算第三轮计算第四轮计算算法总结 C实现Dijkstra算法 Dijkstra算法简介 Dijkstra算法计算是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起…

1929-2022年全球气象站点的逐日平均能见度

气象数据是我们在各项研究中都非常常用的数据,之前我们分享过全球范围的1929-2022年的具体到气象站点的逐日气象数据,包括平均气温、最高气温、最低气温、平均风速(可查看之前的文章获取)。 本次我们带来的是全球范围的1929-2022…

单链表的成环问题

前言:链表成环问题不仅考察双指针的用法,该问题还需要一定的数学推理和分析能力,看似简单的题目实则细思缜密,值得斟酌~ 目录 1.问题背景引入-判断链表是否成环: 1.1.正解:快慢指针 1.2 STL的集合判重 …

kubespray部署k8s 1.26集群安装指南

Kubespray 是一个自由开源的工具,它提供了 Ansible 剧本(playbook) 来部署和管理 Kubernetes 集群。它旨在简化跨多个节点的 Kubernetes 集群的安装过程,允许用户快速轻松地部署和管理生产就绪的 Kubernetes 集群。 它支持一系列操作系统,包…

Spring的第十五阶段:Spring的事务管理(02)

1、自定义设置回滚异常 rollbackFor和rollbackForClassName回滚的异常 /*** Transactional 表示使用通知( 启用事务 ) <br/>* rollbackFor 属性可以自定义哪些异常可以回滚事务 <br/>* rollbackForClassName 属性可以自定义哪些全类名的异常回滚事务 <br/>…

Java实现八大排序

&#x1f495;“汲取知识&#xff0c;分享快乐&#xff0c;让生命不留遗憾”&#x1f495; &#x1f386;作者&#xff1a;不能再留遗憾了&#x1f386; &#x1f43c;专栏&#xff1a;Java学习&#x1f43c; &#x1f3c0;该文章主要内容&#xff1a;直接插入排序、希尔排序、…

VMware安装Ubuntu系统

VMware安装Ubuntu系统 1.首先选择文件&#xff0c;点击新建虚拟机 2.选择自定义&#xff0c;点击下一步 3.点击下一步 4.选择稍后安装操作系统&#xff0c;点击下一步 5.选择Linus操作系统&#xff0c;版本选择Ubuntu64位&#xff0c;点击下一位 6.自己看图 7. 这里根据自…

「2023 最新」 Github、Gitlab Git 工作流「常用」 git 命令、规范以及操作总结 Rebase

Git commit 规范 关于提交信息的格式&#xff0c;可以遵循以下的规则&#xff1a; feat: 新特性&#xff0c;添加功能fix: 修改 bugrefactor: 代码重构docs: 文档修改style: 代码格式修改test: 测试用例修改chore: 其他修改, 比如构建流程, 依赖管理 Git 基础知识 当我们通过…