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

相关文章

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

韦季李输入法_输入法和鼠标的深度融合

在数字化输入的新纪元,传统键盘输入方式正悄然进化。以往,面对实体键盘,我们常需目光游离于屏幕与键盘之间,以确认指尖下的精准位置。而屏幕键盘虽直观可见,却常因占据屏幕空间,迫使我们在操作与视野间做出妥协,频繁调整布局以兼顾输入与界面浏览。 幸而,韦季李输入法的横空出世,彻底颠覆了这一现状。它不仅对输入界面进行了革命性的重构,更巧妙地将鼠标这一传统外设融入其中,开创了一种前所未有的交互体验。 想象

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输