单手杀穿经典链表题Pt.3——LeetCode天梯渡劫(相交链表,环形链表,随机指针链表的深度拷贝)

本文主要是介绍单手杀穿经典链表题Pt.3——LeetCode天梯渡劫(相交链表,环形链表,随机指针链表的深度拷贝),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

    • 传统艺能😎
    • 相交链表🤔
    • 环形链表🤔
    • 环形链表 II🤔
    • 复制带随机指针的链表🤔

传统艺能😎

小编是双非本科大一菜鸟不赘述,欢迎大佬指点江山(QQ:1319365055)
此前博客点我!点我!请搜索博主 【知晓天空之蓝】
乔乔的gitee代码库(打灰人 )欢迎访问,点我!

🎉🎉非科班转码社区诚邀您入驻🎉🎉
小伙伴们,打码路上一路向北,背后烟火,彼岸之前皆是疾苦
一个人的单打独斗不如一群人的砥砺前行
这是我和梦想合伙人组建的社区,诚邀各位有志之士的加入!!
社区用户好文均加精(“标兵”文章字数2000+加精,“达人”文章字数1500+加精)
直达: 社区链接点我

你一定要走,走到灯火通明

——卢思浩《你要去相信,没有到不了的明天》

在这里插入图片描述

相交链表🤔

链接:相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
题目数据 保证 整个链式结构中不存在环。注意,函数返回结果后,链表必须 保持其原始结构 。如果程序能够正确返回相交节点,那么你的解决方案将被视作正确答案

示例:
在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

思路:解题方法比较清奇,有点快慢指针内味,但并非快慢指针,我们要构筑相同路程,为什么?因为两个不等长的链表相交,指针走位不同步就无法比对内容。

只有两个链表不为空是才可能相交,那么链表最后尾节点内容和地址是必然相同的,所以我们重点是同步指针,让他们同时到达尾节点,链表 A 不重叠部分长度为 x,链表 B 不重叠部分长度为 y ,两链表重叠部分长度为 z,遍历两个链表时,A 变成 NULL就让指针指向链表 B 的头结点,B 变成 NULL就让指针指向链表 A 的头结点,抽象个图出来就是这样:

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode *p1 = headA;struct ListNode *p2 = headB;   while(p1 != p2){if(p1==NULL){p1 = headB;}else{p1 = p1->next;}if(p2==NULL){p2 =headA;}else{p2 =p2->next;}}return p1;
}

~
在这里插入图片描述

环形链表🤔

链接:环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

在这里插入图片描述
思路:有请我们的老朋友:快慢指针!!!在这里插入图片描述
知不知道双指针的含金量啊铁咩!我们既然是环形链表就不怕走到头,只管去找就行了,快指针一次走两步,慢指针一次走一步,遍历的边界就是快指针遍历完两遍链表,这时候慢指针刚好遍历完一遍,如果快指针遇到了慢指针就说明有猫腻。

bool hasCycle(struct ListNode *head) {struct ListNode *slow = head;struct ListNode *fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow==fast)return  true;}return false;
}

~
在这里插入图片描述

环形链表 II🤔

链接:环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,不允许修改 链表。

这道题是力扣的中等难度题,他奈奈滴,说的芥末复杂,其实就是在原来判读环形链表基础上多了步找到环形节点罢了。

struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *cur = head;struct ListNode *tail = head;while(tail && tail->next){cur = cur->next;tail = tail->next->next;//判断环形链表if(cur == tail){struct ListNode *head2 = tail;struct ListNode *p1 = head2;struct ListNode *p2 = head;//   tail =NULL;while(p1 != p2){p1 = p1==NULL?head:p1->next;p2 = p2==NULL?head2:p2->next;}//同上上一题,构筑相同路程找到该节点return p1;}
}
return NULL;
}

~
在这里插入图片描述

复制带随机指针的链表🤔

链接:复制带随机指针的链表

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

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

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有
x.random --> y 。 返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 val:一个表示 Node.val 的整数
random_index:随机指针指向的节点索引(范围从 0 到 n-1) 如果不指向任何节点,则为 null 。你的代码 只
接受原链表的头节点 head 作为传入参数。

示例:
在这里插入图片描述
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]

思路:不开玩笑的说,这道题才配得上力扣给的中等难度,我读懂题目的时候已经老泪纵横了,再看看示例的图直接给我干破防了
在这里插入图片描述

思路:这道题本质就是一个深度拷贝,最大的难点就是如何处理所谓的随机指针,指向随机内容的指针到底该怎么去链接呢?就只有一个办法那就是顺藤摸瓜,从头节点一路向北,不就是复制这个链表吗,那我先创建一个一模一样的链表出来,但是这可不是简简单单复制出来就行,这还是个技术活诶,我们采用尾随式拷贝:
在这里插入图片描述
这种结构的好处就是可以跟进,在复制阶段可以靠拷贝节点的前一个节点(原节点)的随机指针来跟进到复制链表中找到拷贝节点的随机指针,从而达到深度拷贝的目的,逻辑结构就是拷贝节点指向的随机节点是拷贝节点前一个节点的随机指针指向的节点的下一个:
在这里插入图片描述
整个链表就构建完成了,要得到我们的成品就要将原来链表和拷贝链表分离,最后重组拷贝链表就行了。
总结一下就是三步走战略

  1. 原链表每个节点后复制这个节点,与原链表相连形成新链表;
  2. 遍历链表,让 p->next->random = p->random->next ,以此完成链表的拷贝;
  3. 将原链表和拷贝链表拆分,再重组出拷贝链表即可
struct Node* copyRandomList(struct Node* head) {if(head==NULL){return NULL;}//新建拷贝链表struct Node* cur = head;while(cur){struct Node* new = (struct Node*)malloc(sizeof(struct Node));new->val =  cur->val;new->next = cur->next;//与拷贝节点链接成新链表cur->next = new;cur = cur->next->next;}cur = head;//处理random指针while(cur){struct Node* node = cur->next;if(cur->random == NULL){node->random = NULL;}else{node->random = cur->random->next;}cur = cur->next->next;}//重建链表(解下再链接)cur = head;struct Node* copyhead=NULL;struct Node* copytail=NULL;while(cur){struct Node* copy = cur->next;struct Node* next = copy->next;cur->next = next;if(copyhead==NULL){copytail=copyhead=copy;}else{copytail->next = copy;copytail = copytail->next;}cur =next;}
return copyhead;
}

思路理解起来并不难,但是过程中很多细节需要自己去慢慢打磨,这是一个很不错的题目,如果你可以很顺利做出来,那么恭喜你,你对链表的理解已经满分了。

~
在这里插入图片描述

这篇关于单手杀穿经典链表题Pt.3——LeetCode天梯渡劫(相交链表,环形链表,随机指针链表的深度拷贝)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/409936

相关文章

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Python中随机休眠技术原理与应用详解

《Python中随机休眠技术原理与应用详解》在编程中,让程序暂停执行特定时间是常见需求,当需要引入不确定性时,随机休眠就成为关键技巧,下面我们就来看看Python中随机休眠技术的具体实现与应用吧... 目录引言一、实现原理与基础方法1.1 核心函数解析1.2 基础实现模板1.3 整数版实现二、典型应用场景2

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Redis中高并发读写性能的深度解析与优化

《Redis中高并发读写性能的深度解析与优化》Redis作为一款高性能的内存数据库,广泛应用于缓存、消息队列、实时统计等场景,本文将深入探讨Redis的读写并发能力,感兴趣的小伙伴可以了解下... 目录引言一、Redis 并发能力概述1.1 Redis 的读写性能1.2 影响 Redis 并发能力的因素二、

最新Spring Security实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)

《最新SpringSecurity实战教程之表单登录定制到处理逻辑的深度改造(最新推荐)》本章节介绍了如何通过SpringSecurity实现从配置自定义登录页面、表单登录处理逻辑的配置,并简单模拟... 目录前言改造准备开始登录页改造自定义用户名密码登陆成功失败跳转问题自定义登出前后端分离适配方案结语前言

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Python与DeepSeek的深度融合实战

《Python与DeepSeek的深度融合实战》Python作为最受欢迎的编程语言之一,以其简洁易读的语法、丰富的库和广泛的应用场景,成为了无数开发者的首选,而DeepSeek,作为人工智能领域的新星... 目录一、python与DeepSeek的结合优势二、模型训练1. 数据准备2. 模型架构与参数设置3

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操