单手杀穿经典链表题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

相关文章

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?

Java集合中的链表与结构详解

《Java集合中的链表与结构详解》链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序的通过链表中的引用链接次序实现,文章对比ArrayList与LinkedList的结构差异,详细讲解了链表... 目录一、链表概念与结构二、当向单链表的实现2.1 准备工作2.2 初始化链表2.3 打印数据、链表长

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499