力扣 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 作为传入参数。

思路:

题目要求我们拷贝一个带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 1struct 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.hqwc.cn/news/162601.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端框架Vue学习 ——(三)Vue生命周期

生命周期&#xff1a;指一个对象从创建到销毁的整个过程。 生命周期的八个阶段&#xff1a;每触发一个生命周期事件&#xff0c;会自动执行一个生命周期方法&#xff08;钩子&#xff09; mounted&#xff1a;挂载完成&#xff0c;Vue 初始化成功&#xff0c;HTML 页面渲染成功…

京东商品详情API接口(PC端和APP端),京东详情页,商品属性接口,商品信息查询

京东开放平台提供了API接口来访问京东商品详情。通过这个接口&#xff0c;您可以获取到商品的详细信息&#xff0c;如商品名称、价格、库存量、描述等。 以下是使用京东商品详情API接口的一般步骤&#xff1a; 注册并获取API权限&#xff1a;您需要在京东开放平台上注册并获取…

ClickHouse 学习之从高级到监控以及备份(二)

第 一 部分 高级篇 第 1 章 Explain 查看执行计划 在 clickhouse 20.6 版本之前要查看 SQL 语句的执行计划需要设置日志级别为 trace 才能可以看到&#xff0c;并且只能真正执行 sql&#xff0c;在执行日志里面查看。在 20.6 版本引入了原生的执行计划的语法。在 20.6.3 版本成…

微信小程序之自定义组件开发

1、前言 从小程序基础库版本 1.6.3 开始&#xff0c;小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。开发者可以将页面内的功能模块抽象成自定义组件&#xff0c;以便在不同的页面中重复使用&#xff1b;也可以将复杂的页面拆分成多个低耦…

如何使用Node.js快速创建HTTP服务器并实现公网访问本地Server

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

【stack题解】最小栈 | 栈的压入、弹出序列

目录 最小栈 思路 ​编辑 实现 栈的压入、弹出序列 思路 实现 需要注意的 最小栈 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。…

Git 的基本操作 ——命令行

Git 的工作流程 详解如下&#xff1a; 本地仓库&#xff1a;是在开发人员自己电脑上的Git仓库,存放我们的代码(.git 隐藏文件夹就是我们的本地仓库) 远程仓库&#xff1a;是在远程服务器上的Git仓库,存放代码(可以是github.com或者gitee.com 上的仓库,或者自己该公司的服务器…

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 …

家用好物风云汇,值得买风尚购物清单

双十一又要来啦&#xff01;作为购物狂热者的我们&#xff0c;肯定早已经在各大电商平台上准备好了购物清单。但是&#xff0c;如果你还没有找到心仪的好物&#xff0c;那么不妨来看看值得买在线上线下的选品活动。 最近&#xff0c;我在风尚场发现了很多值得买的家用好物&…

2023 electron最新最简版windows、mac打包、自动升级详解

这里我将讲解一下从0搭建一个electron最简版架子&#xff0c;以及如何实现打包自动化更新 之前我有写过两篇文章关于electron框架概述以及 常用api的使用&#xff0c;感兴趣的同学可以看看 Electron桌面应用开发 Electron桌面应用开发2 搭建electron 官方文档&#xff1a;ht…

数据结构—字符串

文章目录 7.字符串(1).字符串及其ADT#1.基本概念#2.ADT (2).字符串的基本操作#1.求子串substr#2.插入字符串insert#3.其他操作 (3).字符串的模式匹配#1.简单匹配(Brute-Force方法)#2.KMP算法I.kmp_match()II.getNext() #3.还有更多 小结附录&#xff1a;我自己写的string 7.字符…

【CSS】div 盒子居中的常用方法

<body><div class"main"><div class"box"></div></div> </body>绝对定位加 margin: auto; &#xff1a; <style>* {padding: 0;margin: 0;}.main {width: 400px;height: 400px;border: 2px solid #000;positio…