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

news2024/11/20 14:40:09
  • Leetcode 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 作为传入参数。

在这里插入图片描述


解题思路

  • 相信有的人还没看懂这个题目的描述。 其实该题意思是 把原来链表复制一份,在不更改原链表的情况下返回拷贝链表

这题需要对指针的操作和使用有一定的理解和熟练掌握。对链表指针控制要求非常高,一但出错就会out了.所以我们要十分的小心。

  • 解题思路
  1. 拷贝节点。
  • 假设我们现在遍历到原链表的某个节点cur,我们需要先创建一个新节点,然后将新节点插入到cur和cur.next之间。这样,原链表上的所有节点都会被拆成原节点和拷贝节点交替出现的形式。比如原来是 A -> B -> C,现在变成了 A -> A’ -> B -> B’ -> C -> C’
    在这里插入图片描述
  1. 控制拷贝节点的random
  • 我们需要遍历链表将每个拷贝节点的 random 指针指向其对应的原节点random指针指向的节点的拷贝节点. 即 copy->random = cur->random->next。这里需要注意,对于原链表上的任意一个节点假设是cur,如果其 cur->random 指针指向节点,那么其拷贝节点的random指针指向的就应该是cur->random->next的拷贝节点。
  • 举个例子,假设原链表的节点A的random指针指向了节点B,那么A的拷贝节点A’的random指针应该指向B的拷贝节点B’.
  • 当然还有一个情况,就是当节点cur->random == NULL时,我们也应该把拷贝节点copy->random 置空
    在这里插入图片描述
  1. 拆分链表,恢复原链表,并组成拷贝链表
  • 我们需要将链表拆分为原链表和拷贝链表两个链表。我们可以先创建两个指针,一个指向拷贝链表的头部,一个指针来遍历记录该链表的拷贝节点.
    1 . copytail指针用来遍历原链表,copyhead指向作为拷贝链表的头节点.
    2 . copytail->next指向的是原链表的下一个节点,也就是下一个原节点的下一个拷贝节点,copytail每次向后移动两个位置即可遍历原链表中的原节点。
  1. 返回拷贝头节点

运行代码

  • C
struct Node* copyRandomList(struct Node* head) {
    // 1. 拷贝节点,并将其插入到原链表对应节点的后面
    struct Node* cur = head;
    while (cur) {
        // 创建新节点
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val = cur->val;

        // 将新节点插入到cur和cur.next之间
        struct Node* Pnext = cur->next;
        cur->next = copy;
        copy->next = Pnext;
        
        // 指向下一个原节点或下一个拷贝节点
        cur = Pnext;
    }

    // 2. 控制拷贝节点的random
    cur = head;
    while (cur) {
        // 获取原节点的拷贝节点
        struct Node* copy = cur->next;
        // 获取下一个原节点
        struct Node* tmp = copy->next;

        // 原节点的random指针为空,拷贝节点的random指针也为空
        if (cur->random == NULL) {
            copy->random = NULL;
        }
        else {
            // 根据原节点的random指针,获取其对应的拷贝节点,将拷贝节点的random指针指向其对应的拷贝节点
            copy->random = cur->random->next;
        }

        // 移动指针
        cur = tmp;
    }

    // 3. 拆分链表,恢复原链表,并组成拷贝链表
    cur = head;
    struct Node* copyHead = NULL;
    struct Node* copyTail = NULL;
    while (cur) {
        // 获取原节点的拷贝节点
        struct Node* copy = cur->next;
        // 获取下一个原节点
        struct Node* Next = copy->next;

        // 如果是第一个被拼接的拷贝节点,其也就是新链表的头节点
        if (copyHead == NULL) {
            copyHead = copyTail = copy;
        }

        // 如果不是第一个被拼接的拷贝节点,将其拼接到新链表的尾部
        else {
            copyTail->next = copy;
            copyTail = copy;
        }

        // 将cur和copy两个链表中的相应节点分离,恢复原链表
        cur->next = Next; 
        cur = Next;		 
    }

    // 4 返回拷贝链表的头节点
    return copyHead;
}

  • C++
class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (!head) {
            return nullptr;
        }

        // 1. 拷贝节点,并将其插入到原链表对应节点的后面
        Node* cur = head;
        while (cur) {
            // 创建新节点
            Node* copy = new Node(cur->val);

            // 将新节点插入到cur和cur.next之间
            Node* Pnext = cur->next;
            cur->next = copy;
            copy->next = Pnext;

            // 指向下一个原节点或下一个拷贝节点
            cur = Pnext;
        }

        // 2. 控制拷贝节点的random
        cur = head;
        while (cur) {
            // 获取原节点的拷贝节点
            Node* copy = cur->next;
            // 获取下一个原节点
            Node* tmp = copy->next;

            // 原节点的random指针为空,拷贝节点的random指针也为空
            if (cur->random == NULL) {
                copy->random = NULL;
            }
            else {
                // 根据原节点的random指针,获取其对应的拷贝节点,将拷贝节点的random指针指向其对应的拷贝节点
                copy->random = cur->random->next;
            }

            // 移动指针
            cur = tmp;
        }

        // 3. 拆分链表,恢复原链表,并组成拷贝链表
        cur = head;
        Node* copyHead = nullptr;
        Node* copyTail = nullptr;

        while (cur) {
            // 获取原链表的拷贝节点和下一个节点
            Node* copy = cur->next;
            Node* Next = copy->next;

            // 如果是第一个被拼接的拷贝节点
            if (copyHead == nullptr) {
                copyHead = copyTail = copy;
            }
            // 如果不是第一个被拼接的拷贝节点,将其拼接到新链表的尾部
            else {
                copyTail->next = copy;
                copyTail = copy;
            }

            // 将原链表和拷贝链表中的相应节点分离,恢复原链表
            cur->next = Next;
            cur = Next;
        }

        // 4. 返回拷贝链表的头节点
        return copyHead;
    }
};

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

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

相关文章

C语言中这么骚的退出程序方式你知道几个?

前言 在本篇文章当中主要给大家介绍C语言当中一些不常用的特性,比如在main函数之前和之后设置我们想要执行的函数,以及各种花式退出程序的方式。 1、main函数是最先执行和最后执行的函数吗? 1)C语言构造和析构函数 通常我们在…

Python数据分析案例27——PCA-K均值-轮廓系数客户聚类

本案例适合应用统计,数据科学,电商专业 K均值对客户进行分类的案例都做烂了......但我认为这个案例还是有一定的价值的,使用了pca,还有轮廓系数寻找最优的聚类个数。 下面来看看 代码准备 导入包 import numpy as np import pa…

网上学影视后期靠谱吗 影视后期剪辑需要学什么

影视后期如果有人手把手当面教的话,当然是最好的。但很多人都没有这么好的条件,实际上,网上也有很多教程可以学习利用。不过,小伙伴们可能会有疑问,网上学影视后期靠谱吗,影视后期剪辑需要学什么&#xff1…

从创意造型到高品质曲面的卓越体验|CATIA ICEM Design Experience

目录 IDX为设计师提供了强大直观的建模工具 IDX为曲面工程师提供高品质数字模型处理能力 IDX与其他工具配合形成完整的数字化解决方案 建模是设计工作的重要环节,合适的数字模型能够在各个环节对整个设计流程产生正面的推动作用。 设计的不同阶段对模型有各自的…

Azkaban从入门到精通以及案例实操系列

1、Azkaban概论 1.1、Azkaban简介 Azkaban 是一个开源的基于 Web 的工作流调度系统,由 LinkedIn 公司开发并维护。它可以帮助用户在大规模数据处理中来管理和调度作业,提供了简单易用、高效可靠的工作流设计和调度功能。 Azkaban 的主要特点包括&…

亿发ERP系统,全链条采购协同管理数智化平台,中小企业采购业务全流程管理

在数字时代,中小型企业在采购管理方面面临多项挑战。 集采管理难:由于资源和专业知识有限,中小企业通常难以建立集中采购职能,无法有效简化整个组织的采购活动。这一挑战包括定义采购政策、标准化程序和实施高效的采购系统。 信…

『赠书活动 | 第六期』《“Java四大名著“,你集齐了吗?》

💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! 『赠书活动 | 第六期』 本期书籍:《“Java四大名著”,你集齐了吗?》 赠书规则:评论区:点赞&…

供水管网监测系统,供水管网压力监测系统

水是城市赖以生存的血脉,直接关系到居民、企业和公共设施的正常生活和生产。然而,城市供水管网的高效运行面临着一系列挑战,如管道老化、泄漏和不均衡的供水压力等。 目前城市供水管网泄漏检测排查采用人工巡检、人工听漏的方式,巡…

Flutter3.10版本发布,编程语言的重大更新

Flutter是一款强大的跨端开发框架,可以帮助开发者构建高性能、美观、灵活的应用程序,从而实现跨平台开发和部署。小程序容器技术与跨端框架结合使用,为开发者提供一站式的小程序开发和发布服务,帮助他们更加轻松和高效地构建和部署…

CPU和GPU前端的应用

1、CPU(英文Central Processing Unit 中央处理器) CPU(中央处理器)是一种通用的处理器,其主要任务是执行计算机程序中的指令和序列。它能够处理复杂的逻辑判断、分支、跳转、内存访问等操作,因此在执行大多…

虚幻引擎4利用粒子系统实现物体轨迹描绘2- 消除轨迹

目录 前言粒子频繁产生对系统运行的影响轨迹的清除小结 前言 之前已经实现了UE4中跟随物体利用粒子系统产生轨迹的效果,文章链接如下: 虚幻引擎4利用粒子系统实现物体轨迹描绘_ADi_hhh的博客-CSDN博客 但是上篇文章还留下了两个问题 轨迹如何清除&am…

Spring探索——既生@Resource,何生@Autowired?

提到Spring依赖注入,大家最先想到应该是Resource和Autowired,很多文章只是讲解了功能上的区别,对于Spring为什么要支持两个这么类似的注解却未提到,属于知其然而不知其所以然。不知大家在使用这两个注解的时候有没有想过&#xff…

mysql8.0主从复制搭建

mysql8.0主从复制搭建 1.安装两个相同版本8.0的mysql数据库 主从IP端口主库192.168.139.1283306从库192.168.139.1303306 2.主从复制配置 2.1 修改mysql配置文件my.conf 主机mysql配置完整 [mysql] # 设置mysql客户端默认字符集 default-character-setutf8mb4 [client] # …

二十三种设计模式第十篇--外观模式

在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门(政务窗口 )能解决一切手续问题就好了。 软件设计也是这样,当一个系统的功能越来越强&…

2023年小型水库安全监测能力提升解决方案

一、方案背景 2023年小型水库安全监测能力提升试点项目建设将按照“统一规划、统一标准、统一实施、统一管理、统一支撑”的工作要求,对全区小型水库雨水情测报和监测设施建设项目按高水平、高标准、高质量要求开展安全监测能力提升建设,同步开展水工程安…

ZeLinAI是什么?国产ChatGPT快速搭建自己的AI应用

ChatGPT使用门槛高,需要科学上网短信接码等,不如直接选择国产ZelinAI,使用超简单轻轻松松从0到1零代码创建自己的AI应用。目前模型仅支持GPT-3.5-turbo,后续应该会接入文心一言、GPT-4、GPT-4.5和Bard,新手站长分享国产…

DL.to 最新研究(论文)推荐——分割、CVPR、扩散模型、感受野注意力模块

目录 一、CVPR 1.CrowdCLIP:基于视觉-语言模型的无监督人群计数 CrowdCLIP: Unsupervised Crowd Counting via Vision-Language Model 2.Beyond mAP:更好地评估实例分割 Beyond mAP: Re-evaluating and Improving Performance in Instance Segmentation with Se…

基于低代码平台的多租户解决方案

在云计算时代,“多租户”是一个非常重要的概念。根据百度百科中的定义,多租户技术是一种软件架构技术,简单来说是指以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍然可以保障客户的数据在多租户环境中&#xf…

Redis之bitmap/hyperloglog/GEO

Redis之bitmap/hyperlog/GEO 一 面试题引入二 统计的类型三 hyperloglog3.1 行业术语3.2 hyperloglog基础3.2.1 基数3.2.2 定义3.2.3 基数统计3.2.4 基本命令 3.3 HyperLogLog原理3.3.1 去重复统计的方式3.3.2 原理 3.4 HyperLogLog案例实战3.4.1 需求3.4.2 方案讨论3.4.3 Hype…

五、SpringMVC从入门到入坟

一、SpringMVC概念 SpringMVC 是 Spring 框架中的一个模块,它是一个基于 MVC设计模式的 Web 框架,用于构建基于 Java 技术的 Web 应用程序。Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。 它的主要原理是将 Web 应用程序分成模型&…