力扣 138. 随机链表的复制

news2024/11/25 10:51:08

题目描述:

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

思路:

题目要求我们拷贝一个带next指针与random随机访问指针的链表。

如果拷贝一个只带next指针的链表话呢,很简单,根据next依次遍历目标链表,再依次拷贝每个节点的信息就可以了.

一步一步来,我们可以先根据next“这条线” 先拷贝一个新的链表出来。

为什么不是优先根据random指针来拷贝呢?

这是因为random指针指向的是随机节点,可能有环存在,而且,random指向的节点有可能是很后面才出现的节点,而next在题目给出节点目标信息时关系就确定是线性不成环的,所以我们优先考虑拷贝next联系。

 如何拷贝各个节点的random联系呢?--本题重点

首先,我们假设每一个random关系是一条有向边,在旧链表中存在random关系(A)-->(B),

那么对应的,我们想让复制出来的新链表也有这么一条边,且为(a)-->(b)

那么如果我们能通过(A)找到(a),通过(B)找到(b),在遍历旧链表的random关系链中,我们就能顺便建立复制体的关系。(其中节点a是A的复制节点,b是B的复制节点)

也就是说,只要我们能通过某种联系找到自己的复制体,那么我们就能复制random联系。

于是题目的关键转移到了如何将这种联系该存下来且能快速找到呢?

根据哈希思想给出以下解法:

解法一:

如果是c++的话,可以用STL库中的map容器来存下旧链节点在新链的复制体节点。

也就是达到hash[A]=a,hash[B]=b.

unordered_map<Node *, Node *> Hash({{NULL, NULL},{head, newhead}});

我这里照顾只学了c语言的朋友,主要讲方法二,不用map容器。

解法二:

改变旧链表的next,使其在被复制完后指向对应的复制体节点。

这里说的复制完是指复制val信息,以及next联系.

在复制next信息时,假设遍历到了A节点,首先用一个临时遍历temp存放A->next。

当我们创造出来了复制体a节点,我们让A->next=a,然后,a->random=A->random.

在将temp里的节点取出来继续遍历。

为什么要 a->random=A->random?

这是因为由于我们已经破坏了目标链表的next关系,我们之后再想复制random关系就不能再遍历旧链表了,仅依靠random关系可能出现环等问题,所以要想复制random关系,我们就要遍历新链表,也就是刚被复制出来的不完全体。

遍历到当前节点a,我们想要找a 的random应该指向哪里,我们可以先找到A的random指向的B,再通过B->next找到b,又因为A的random终点已经被赋给了a->random,所以就有了最重要的一步:

a->random=a->random->next.

这里a->random->next就是指向b节点。

重复以上步骤,就可以将所有random关系复制下来。

解法三:

思路和方法二差不多,只不过是将a->next=A -->next  然后A->next=a.这样一来,在破坏旧链的next关系后我们通过依旧可以通过A->next->next找到原来A的下一个节点。

这样我们再将a->random=A->random->next(先在目标链中找到B,再通过B->next找到b).

这个方法只不过是恢复了旧链的可遍历性而已,和方法二差不多。

代码:

#define _CRT_SECURE_NO_WARNINGS 1

struct Node* copyRandomList(struct Node* head) {
    if (head == NULL)return NULL;
    struct Node* phead = head;
    struct Node* newhead = (struct Node*)malloc(sizeof(struct Node));//新链的头指针
    struct Node* np = newhead;
    struct Node* star = newhead;
    while (phead) {
        struct Node* t = phead->next;//临时变量,存放phead的下一个节点,防止丢失
        newhead->val = phead->val;
        newhead->random = phead->random;//为了方便后续建立random联系
        phead->next = newhead;//哈希的思想,建立新、旧两个节点的联系
        if (t == NULL) {//如果下一个节点是NULL,就不用开辟空间了
            newhead->next = NULL;
        }
        else {//否则就创造一个节点空间,建立next关系
            newhead->next = (struct Node*)malloc(sizeof(struct Node));
            newhead = newhead->next;
        }
        phead = t;
    }

    while (np != NULL) {
        if (np->random != NULL) {
            np->random = np->random->next;//通过旧链找到新链应该指向的节点
        }
        np = np->next;
    }
    return star;

}

总结:

这个题总的来说不难,如果想用c写出来的话就要求对链表比较熟悉,还是比较考验基本功滴!

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

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

相关文章

NOIP2023模拟12联测33 总结

NOIP2023模拟12联测33 总结 文章目录 NOIP2023模拟12联测33 总结比赛过程正解A. 构造题目大意思路 思路B.游戏题目大意思路 C. 数数题目大意 D. 滈葕题目大意思路 总结 比赛过程 先看了一眼 T 1 T1 T1 &#xff0c;发现又是恶心构造题&#xff0c;果断跳过。 T 2 T2 T2 期望题…

Luckysheet 实现excel多人在线协同编辑

前言 前些天看到Luckysheet支持协同编辑Excel&#xff0c;正符合我们协同项目的一部分&#xff0c;故而想进一步完善协同文章&#xff0c;但是遇到了一下困难&#xff0c;特此做声明哈&#xff0c;若侵权&#xff0c;请联系我删除文章&#xff01; 若侵犯版权、个人隐私&#x…

Flink的API分层、架构与组件原理、并行度、任务执行计划

Flink的API分层 Apache Flink的API分为四个层次&#xff0c;每个层次都提供不同的抽象和功能&#xff0c;以满足不同场景下的数据处理需求。下面是这四个层次的具体介绍&#xff1a; CEP API&#xff1a;Flink API 最底层的抽象为有状态实时流处理。其抽象实现是Process Functi…

MySQL -- 索引

MySQL – 索引 文章目录 MySQL -- 索引一、索引简介1.简介2.索引效率的案例 二、认识磁盘1.磁盘2.结论3.磁盘随机访问(Random Access)与连续访问(Sequential Access) 三、MySQL 与磁盘交互基本单位1.基本单位2.MySQL中的数据管理 五、索引的理解1.索引案例2.单页mysql page3.管…

“七人拼团模式:创新玩法助力平台快速裂变引流“

七人拼团模式是一种结合了社交电商和拼购玩法的快速裂变引流模式。这种模式通过抽取平台营业所得作为奖励补贴用户&#xff0c;以更人性化的奖励机制吸引用户&#xff0c;服务用户&#xff0c;以此加快用户向粉丝的转变&#xff0c;为平台拉取有效流量。本文将介绍七人拼团模式…

二十、泛型(2)

本章概要 泛型接口泛型方法 变长参数和泛型方法一个泛型的 Supplier简化元组的使用一个 Set 工具 泛型接口 泛型也可以应用于接口。例如 生成器&#xff0c;这是一种专门负责创建对象的类。实际上&#xff0c;这是 工厂方法 设计模式的一种应用。不过&#xff0c;当使用生成…

基础课23——设计客服机器人

根据调查数据显示&#xff0c;使用纯机器人完全替代客服的情况并不常见&#xff0c;人机结合模式的使用更为普遍。在这两种模式中&#xff0c;不满意用户的占比都非常低&#xff0c;不到1%。然而&#xff0c;在满意用户方面&#xff0c;人机结合模式的用户满意度明显高于其他模…

freertos简单串口

先来完善一下FreeRTOSConfig.h这个配置文件 /*FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.All rights reservedVISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.This file is part of the FreeRTOS distribution.FreeRTOS is …

无代码平台哪家好,盘点最新国内十大无代码零代码平台排名

无代码&#xff08;No Code&#xff09;是一种通过使用可视化界面和预构建的模块来创建应用程序、网站或其他数字化解决方案的方法&#xff0c;不需要编写大量的手动代码。 无代码平台通常包括一些基本的构建块&#xff0c;如表单、按钮、文本框等&#xff0c;用户可以通过拖拽…

用小程序打造品牌网站的效果如何

网站是企业线上门户&#xff0c;很多企业或商家在成立之初就会选择搭建企业官网展示品牌、承载信息及服务相关预约咨询等&#xff0c;当然除了搭建网页外&#xff0c;还可以通过小程序实现官网效果。 除了浏览器流量外&#xff0c;如微信、百度、头条抖音、支付宝、快手等平台…

ACWing.第 128 场周赛 (B、C题解)

B、5286. 翻倍&#xff08;思维推导&#xff09; 一、题目要求 给定两个正整数&#xff0c;初始时两数均为 1。 你可以进行任意次&#xff08;也可以不进行&#xff09;翻倍操作&#xff0c;每次操作任选一个非负整数 k&#xff0c;令两数中的一个数乘以 k&#xff0c;另一个…

MySQL数据库之表操作

目录 表的操作1.创建表创建表案例 2.查看表结构3.修改表4.删除表 表的操作 1.创建表 语法&#xff1a; CREATE TABLE table_name (field1 datatype,field2 datatype,field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎;说明&#xff1a; field 表示列…

Python异步编程--获取girlypic写真集

前言 在日常生活中&#xff0c;无论是网络配置、文件整理、web开发还是工具&#xff0c;时常用到Python写些脚本。 这次主要是分享下异步编程的经验&#xff0c;就拿获取girlypic的图片举例吧&#xff0c;也希望能给一些同学带来思考。 使用argparse而不是os.args&#xff0…

pytorch直线拟合

目录 1、数据分析 2、pytorch直线拟合 1、数据分析 直线拟合的前提条件通常包括以下几点&#xff1a; 存在线性关系&#xff1a;这是进行直线拟合的基础&#xff0c;数据点之间应该存在一种线性关系&#xff0c;即数据的分布可以用直线来近似描述。这种线性关系可以是数据点…

86.Linux系统下复制进程fork(逻辑地址和物理地址)

目录 fork复制进程 逻辑地址和物理地址 fork复制进程 fork 是一个系统调用&#xff0c;在 Linux/Unix 系统中用于创建一个新的进程&#xff0c;新进程称为子进程。子进程是父进程的副本&#xff0c;它从父进程那里继承了大部分属性和资源&#xff0c;包括代码、数据、打开的文…

【逗老师的无线电】Debian Linux手工编译安装MMDVM

看我干了啥&#xff0c;在Vmware里面装了一个Debian Linux并且运行了MMDVMHost&#xff0c;来支持业余无线电通联 开始之前先举个手&#xff0c;有多少朋友能分清MMDVM和Pi-Star关系的&#xff1f; MMDVM、Pi-Star和树莓派的关系 咱们先科普一下这个小知识点。各位HAM们应…

Python基础(第五期): python数据容器(序列) 列表 集合 元素 字符串 字典 序列遍历操作

python基础专栏 python基础&#xff08;第五期&#xff09; 文章目录 python基础&#xff08;第五期&#xff09;数据容器一、列表1、列表的定义2、列表的下标索引 3、列表的(添加)方法3.1 列表的查询方法3.2 修改特定下标索引的值3.3 列表指定位置插入元素3.3 列表指定元素的追…

自动驾驶高效预训练--降低落地成本的新思路(AD-PT)

自动驾驶高效预训练--降低落地成本的新思路 1. 之前的方法2. 主要工作——面向自动驾驶的点云预训练2.1. 数据准备 出发点&#xff1a;通过预训练的方式&#xff0c;可以利用大量无标注数据进一步提升3D检测 https://arxiv.org/pdf/2306.00612.pdf 1. 之前的方法 1.基于对比学…

setTimeout和setImmediate以及process.nextTick的区别?

目录 前言 setTimeout 特性和用法 setImmediate 特性和用法 process.nextTick 特性和用法 区别和示例 总结 在Node.js中&#xff0c;setTimeout、setImmediate和process.nextTick是用于调度异步操作的三种不同机制。它们之间的区别在于事件循环中的执行顺序和优先级。…

django安装数据库

使用pip安装django pip3 install django注意我使用的是python3所以用pip3安装&#xff0c;如需安装指定版本 django ..* 检测是否安装成功,不报错&#xff0c;则安装成功 # python3 # import django下边这是报错的 django迁移数据库 再mysql中简历数据库 CREATE DATABA…