单链表OJ题:LeetCode--138.复制带随即指针的链表

news2024/11/17 11:45:51

朋友们、伙计们,我们又见面了,本期来给大家解读一下LeetCode中第138道单链表OJ题,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

数据结构与算法专栏数据结构与算法

个  人  主  页 :stackY、

C 语 言 专 栏C语言:从入门到精通

 LeetCode--138.复制带随即指针的链表:https://leetcode.cn/problems/copy-list-with-random-pointer/description/

目录

1.题目介绍

2.实例演示

3.解题思路

::链接拷贝结点 :: 

::找拷贝节点的random ::

:: 拆解拷贝链表 ::


1.题目介绍

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

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

小编现在这里向大家袒露心扉一下:其实我刚刚看到这个单链表OJ题,看了半天连题目都没咋搞明白,好不容易看懂了题目介绍,可是又不知道该从何下手,然后求助各种大佬,才慢慢理解,然后整理思路,在这篇文章中将这道题分享给大家。

2.实例演示

3.解题思路

这道题应该算是单链表OJ题中比较复杂的一道题了,主要是比较难理解。题目的主要意思就是要拷贝出与原链表一模一样的一个链表。那么这道题拷贝链表都不是很复杂,比较难处理的就是这个随即指针random的指向,如果原链表的random指向空那这好说,拷贝链表的也指向空,但是如果原链表的random指向非空,那该如何去找这个random呢?在这里呢,很多老铁喜欢用random指向的值来比较,这种想法可以,但是架不住链表中有相同的值,那么就有许多老铁用它的random指向的地址来比较,这种方法是完全可行的,但是呢,这种暴力求解的方法往往都不是最优解,使用地址来进行比较的话它的时间复杂度是O(N^2),效率也是不太行。所以我们需要寻求更优解

这道题的解题思路我分为了三个步骤:

1. 链接拷贝结点:

 将拷贝结点插入到原结点的后面。

2. 找拷贝节点的random:

通过原链表来控制拷贝结点的随机指针random。

3. 拆解拷贝链表:

将拷贝结点拆下来,依次尾插组成新的链表,然后恢复原链表。

接下来我们一步一步来进行解题:

::链接拷贝结点 :: 

我们可以将拷贝结点链接在原结点的后面,这种方法比较巧妙,有助于我们找随即指针random。

先创建拷贝节点,然后遍历原链表,然后保存头节点的下一个结点,改变指向,将拷贝节点插入到原结点的后面。

图示:

 

代码演示:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
	struct Node* cur = head;

    //1.链接拷贝节点
    while(cur)
    {
        //创建拷贝结点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        //保存头指针的下一个结点
        struct Node* curNext = cur->next;

        //链接
        cur->next = copy;
        copy->next = curNext;
        cur = curNext;
    }
    //......
}

 ::找拷贝节点的random ::

当我们将拷贝结点链接在原结点的后面时,我们需要找拷贝结点的随机指针random,这里可以分为两种情况:

1. 如果原结点的random是空,那么直接将拷贝结点的random置为空即可。

2. 若不为空,那么就需要观察一下这个链表,拷贝结点的random指针指向的就是原结点的random指向的结点的next结点:

                               copy -> random = cur -> random -> next;

因为我们将拷贝结点链接在了原结点的后面,那么原结点的random指向的结点的next结点就是拷贝结点要找的random。我们依旧遍历整个链表,然后将拷贝节点的随机指针链接。

图示:

 

代码演示:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
	struct Node* cur = head;

    //1.链接拷贝节点
    while(cur)
    {
        //创建拷贝结点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        //保存头指针的下一个结点
        struct Node* curNext = cur->next;

        //链接
        cur->next = copy;
        copy->next = curNext;
        cur = curNext;
    }

    //2.找拷贝节点的random 
    //重新返回头
    cur = head;
    while(cur)
    {
        //找拷贝结点
        struct Node* copy = cur->next;
        //找下一个结点
        struct Node* next = copy->next;

        //链接拷贝节点的随机指针random
        if(cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }

        //遍历
        cur = next;
    }
    //......
}

:: 拆解拷贝链表 ::

我们找到了拷贝链表之后呢,需要将这些拷贝的结点组成一个新的链表,这就需要将这些拷贝结点依次进行尾插,然后再将原链表恢复。这就比较简单了:

图示:

 完整代码演示:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) {
	struct Node* cur = head;

    //1.链接拷贝节点
    while(cur)
    {
        //创建拷贝结点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        //保存头指针的下一个结点
        struct Node* curNext = cur->next;

        //链接
        cur->next = copy;
        copy->next = curNext;
        cur = curNext;
    }

    //2.找拷贝节点的random 
    //重新返回头
    cur = head;
    while(cur)
    {
        //找拷贝结点
        struct Node* copy = cur->next;
        //找下一个结点
        struct Node* next = copy->next;

        //链接拷贝节点的随机指针random
        if(cur->random == NULL)
        {
            copy->random = NULL;
        }
        else
        {
            copy->random = cur->random->next;
        }

        //遍历
        cur = next;
    }

    //3.拆解拷贝结点,恢复原链表
    //重新返回头
    cur = head;

    //创建新的链表
    struct Node* copyHead = NULL;
    struct Node* copyTail = NULL;

    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/634430.html

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

相关文章

python使用Faker库进行生成模拟mock数据(基本使用+五个小案例)

使用faker进行生成模拟(mock))数据 文章目录 使用faker进行生成模拟(mock))数据一、Faker库安装二、Faker库基本介绍三、案例1:Faker库生成核酸数据四、案例2:生成不重复的人名和地名五、案例3:生成有时间期限的低保数据六、案例4&#xff1a…

01-Vue 项目环境搭建和创建准备工作

一. 学习目标 掌握 Vue 项目创建的依赖环境掌握 Vue 项目创建过程 二. 学习内容 掌握搭建 Vue 项目准备环境掌握 Vue 项目创建过程了解 Vue 项目各子目录 三. 学习过程 1. 准备工作 (1)安装Node.js 打开node.js官网:Node.js &#xff0…

【状态估计】无迹卡尔曼滤波(UKF)应用于FitzHugh-Nagumo神经元动力学研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

详解ASP.NET Core 在 IIS 下的两种部署模式

KestrelServer最大的优势体现在它的跨平台的能力,如果ASP.NET CORE应用只需要部署在Windows环境下,IIS也是不错的选择。ASP.NET CORE应用针对IIS具有两种部署模式,它们都依赖于一个IIS针对ASP.NET CORE Core的扩展模块。 一、ASP.NET CORE C…

UML类图入门

UML类图入门 UML是一个通用的可视化建模描述语言,通过图形符号和文字来对系统进行建模。适用于各种软件的开发方法、生命周期的各个阶段。 类的UML图示 类使用包含类型、属性和操作(方法)且带有分割线的长方形来表示,如&#x…

人际关系的学习改进

表达的目的:让别人对你感兴趣 不要有苦劳而无功劳 爱的五种语言:表达爱的语言 人类存在的中心,是渴望和人亲近,被人所爱。婚姻即是被设计满足这种亲密关系和爱的需求的;把注意力集中在情绪健康所需的那片爱土上&…

【C++ 程序设计】第 4 章:运算符重载

目录 一、运算符重载的概念 (1)重载运算符的概念 ① 重载运算符的概念 ② 可重载的运算符 ③ 不可重载的运算符 ④ 运算符的优先级 (2)重载运算符为类的成员函数 (3)重载运算符为友元函数 &#…

【Linux】Docker部署镜像环境 (持续更新ing)

防火墙 1、查看防火墙状态 sudo systemctl status ufw 2、开启防火墙 sudo systemctl start ufw 3、关闭防火墙 sudo systemctl stop ufw 4、开机禁止开启防火墙 sudo systemctl disabled ufw 5、开启自启防火墙 sudo systemctl enabled ufw Elasticsearch 1、安装指定版本 比…

使用Pillow库轻松实现图像尺寸调整——>使每个图像具有相同的大小,方便模型处理和训练

在计算机视觉领域,对图像进行尺寸调整是一项非常常见的操作。在训练深度神经网络时,因为计算资源和内存限制的原因,我们通常需要将图像缩放到相同的尺寸。 在本文中,我们将介绍如何使用Python中的Pillow库对图像进行尺寸调整,并提供一个示例程序resize_images。 1. Pytho…

VulnHub靶场-Chronos

目录 0x01 声明: 0x02 简介: 0x03 环境准备: 0x04 信息收集: 1、主机发现 2、NMAP扫描 3、访问业务 4、目录探测 5、查看网页代码 0x05 渗透测试过程: 1、Burp Suite抓包 2、构造payload 测试是否可以外联…

CSS基础学习--5 background背景

一、介绍&#xff1a; CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: background-color 背景颜色background-image 背景图片background-repeatbackground-attachmentbackground-position 二、属性 2.1、background-color 属性定义了元素的背景颜色 <s…

根据word模板生成pdf文件

1、首先建一个word&#xff0c;插入一个表格&#xff0c;需要填充的值用${parame}代替 &#xff08;注意&#xff1a;这里的参数要和java实体类里面的参数对应起来&#xff0c;代码放在下面&#xff09; 2、制作完成后另存为xml格式 3、然后用文本编辑工具打开这个xml文件&…

CSS基础学习--6 CSS Text(文本)

一、文本颜色 color:red; 颜色属性被用来设置文字的颜色。 颜色是通过CSS最经常的指定&#xff1a; 十六进制值 - 如: &#xff03;FF0000一个RGB值 - 如: RGB(255,0,0)颜色的名称 - 如: red body {color:red;} h1 {color:#00ff00;} h2 {color:rgb(255,0,0);} 二、文本的…

【备战秋招】每日一题:4月18日美团春招:题面+题目思路 + C++/python/js/Go/java带注释

2023大厂笔试模拟练习网站&#xff08;含题解&#xff09; www.codefun2000.com 最近我们一直在将收集到的各种大厂笔试的解题思路还原成题目并制作数据&#xff0c;挂载到我们的OJ上&#xff0c;供大家学习交流&#xff0c;体会笔试难度。现已录入200道互联网大厂模拟练习题&a…

8 channel、反射、网络编程【Go语言教程】

8 channel、反射、网络编程【Go语言教程】 1 channel 1.1 概念及快速入门 channel:管道&#xff0c;主要用于不同goroutine之间的通讯 需求&#xff1a;现在要计算 1-200 的各个数的阶乘&#xff0c;并且把各个数的阶乘放入到 map 中。最后显示出来。要求使用 goroutine 完成…

[LeetCode周赛复盘] 第 349 场周赛20230611

[LeetCode周赛复盘] 第 349 场周赛20230611 一、本周周赛总结6470. 既不是最小值也不是最大值1. 题目描述2. 思路分析3. 代码实现 6465. 执行子串操作后的字典序最小字符串1. 题目描述2. 思路分析3. 代码实现 6449. 收集巧克力1. 题目描述2. 思路分析3. 代码实现 6473. 最大和…

测试老鸟总结,接口自动化测试用例设计编写,高级测试之路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口信息来源 与…

百度图像识别 API

首先预览下效果 feaa250077a543a39f037ae8e78a3e80~tplv-k3u1fbpfcp-zoom-in-crop-mark:1512:0:0:0.awebp (640594) (byteimg.com) 从以上预览图中可看出&#xff0c;每张图片识别出5条数据&#xff0c;每条数据根据识别度从高往下排&#xff0c;每条数据包含物品名称、识别度…

VisualStdio中scanf报错问题

VisualStdio中scanf报错问题 目录 一&#xff0e; 概述二&#xff0e; 解决方法 一&#xff0e; 概述 报错代码及说明 报错代码为C4996 会在哪种编译器中报错&#xff1f; VisualStdio系列编译器 为什么会报错&#xff1f; 因为VisualStdio比较严谨&#xff0c;认为scanf不…

内网安全:横向传递攻击( RDP || Cobalt Strike )

内网安全&#xff1a;横向传递攻击&#xff08; RDP || Cobalt Strike &#xff09; 横向移动就是在拿下对方一台主机后&#xff0c;以拿下的那台主机作为跳板&#xff0c;对内网的其他主机再进行后面渗透&#xff0c;利用既有的资源尝试获取更多的凭据、更高的权限&#xff0…