【数据结构与算法】相交链表、环形链表(判断是否有环)、环形链表(返回入环节点)

news2024/11/26 9:25:53

主页:HABUO🍁主页:HABUO

🍁如果再也不能见到你,祝你早安,午安,晚安🍁


1.相交链表

题目:给你两个单链表的头节点 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 个节点。 — 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

分析:拿到这个题,我们最直接的想法就是能不能用我们之前的思想去解决,我们之前大多都是双指针解决的题,那这个题能不能解决呢?答案是肯定的,我们先观察下,如果下面的那个长的链表把多的那一个走了,之后长短链表一块走不久遇到了嘛,诶就是这样😃, 前面我们做了很多快指针要多走几步的题型,在这里我们又遇到了。因此大致思想就是:1.我们需要先知道谁长谁短。2.长的先走完长的步数。3.之后长短一块走,直至地址相同便是相交的节点

我们先计算两个链表的长度,具体如下:

//先求两个链表的长度,判断谁长谁短,长的长多少
Node* curA = headA;
Node* curB = headB;
int sizeA = 1;
int sizeB = 1;
while(curA)
{
    sizeA++;
    curA = curA->next;
}
while(curB)
{
    sizeB++;
    curB = curB->next;
}

之后就是判断谁长谁短,长的先走完长的步数,之后一起走。具体如下所示:

 //判断谁长
    if(sizeA > sizeB)
    {
        int lenth_sub = sizeA - sizeB;
        //长的先走长的步数
        while(lenth_sub--)
        {
            headA = headA->next;
        }
        //之后同时走
        while(headA != headB)
        {
            if(headA == NULL)
            return NULL;
            headA = headA->next;
            headB = headB->next;
        }
        return headA;
    }
    //同样道理
    else
    {
        int lenth_sub = sizeB - sizeA;
        while(lenth_sub--)
        {
            headB = headB->next;
        }
        while(headA != headB)
        {
            if(headA == NULL)
            return NULL;
            headA = headA->next;
            headB = headB->next;
        }
        return headA;
    }

2.环形链表(判断是否有环)

题目:给你一个链表的头节点 head ,判断链表中是否有环。如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例1:

输入:head = [3,2,0,-4], pos = 1

输出:true

解释:链表中有一个环,其尾部连接到第二个节点。 

示例2:

 输入:head = [1], pos = -1

输出:false

解释:链表中没有环。 

分析:看到题我们还是同样的思想能不能用之前解题的方式解决,两个指针,一个快指针一个慢指针,要是有环,快指针是不是先进入环,当慢指针进环时,无论快指针走到哪,是不是就相当于在一个圆里面你追我赶了,只要快慢指针能相遇就说明链表里有环,如果快指针直接遍历完了整个链表后指向NULL,那就是没环。那这里就有了一个追上追不上的问题,虽然快指针走的快,它们之间的距离是逐渐缩小但是如果快靠近的时候跨过去了怎么办?因此必须这样的一个距离是一个单元一个单元缩小,不然无论是偶数还是奇数是不是都有可能永远遇不到,因为偶数如果每次缩小的距离都是奇数那么永远都遇不到, 奇数也是同样的道理。具体见下:

所以思想就是快指针走两步,慢指针走一步,只要遇到就是有环。实现如下:

bool hasCycle(struct ListNode *head) {
    struct ListNode *fast = head , *slow = head;
    while(fast && fast->next)//fast和fast->next不能为NULL,因为fast要走两步
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)//遇到就是有环
        return true;
    }
    return false; //走到这就是fast或者fast->next为NULL说明遍历了整个链表因此也就没环
}

3.环形链表(返回入环节点) 

题目:给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null不允许修改 链表。

示例1:

输入:head = [3,2,0,-4], pos = 1

输出:返回索引为 1 的链表节点

解释:链表中有一个环,其尾部连接到第二个节点。

示例2:

输入:head = [1], pos = -1

输出:返回 null

解释:链表中没有环。

分析:这个题是上一个题的进阶版,上个题只需判断有没有环,这个题不但要有环而且还要返回环的入口节点,怎么做呢?前面有个相交链表,这能不能转换成相交链表呢?显然可以,为什么?因为我们判断环型链表时,是不是只要快慢指针相遇就是有环,那我们要是在这个相遇的这个节点断开是不是就是两个链表找相交节点,如下图所示:

但我说别这样做,前面我们可以看到光找相交节点工作量就比较大,何况我们还需要处理环呢,太繁琐,讨人烦,我们换一种方法,来点小学生的应用题,这不就是你追我赶的题嘛,来两个小方程不就解决了嘛,何必费那么大力气,我们假设slow走了L+X,那么fast是不是就走了2*(L+X),我们假设fast在人生道路上等待心上人等上了N圈,即N*C,是不是还有在slow身后走的X那段距离(众里寻他千百度,那人却在灯火阑珊处),那是不是就是2*(L+X)=L+X+N*C,好整理一下就是L=N*C-X诶发现了什么吗?(强调一遍,此时在fast与slow相遇处哦)是不是就是在相遇的这个点fast你随便走吧一定是走了N*C-X与头节点走了L相遇,那这次相遇就是环的入口节点(fast找到slow不容易啊,是不是回忆了一下这些年的心酸,走到当初那个岔路口思绪万千)。如下图所示:

在第二道环形题的基础上,我们只需让fast和head动起来即可,直至它们相遇,因为它们一定相遇💕。所以实现代码如下:

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast = head , *slow = head;
    while(fast && fast->next)//fast和fast->next不能为NULL,因为fast要走两步
    {
        fast = fast->next->next;
        slow = slow->next;
        if(slow == fast)//遇到就是有环
        {
            while(head != fast)
            {
                head = head->next;
                fast = fast->next;
            }
            return fast;
        }
    }
    return NULL; //走到这就是fast或者fast->next为NULL说明遍历了整个链表因此也就没环
}

总结:本篇博客介绍了三道题,这三道题不约而同的有相似的部分,无论是相交链表,亦或是环形链表,这样新的结构,可以扩展我们的知识面,相信再以后面对不一样的题型时,我们仍然可以迎刃有余,希望大家都有所收获,相信本篇博客的学习我们受益匪浅!💯 


🌻数据结构与算法专栏🌻

🏋不是每一粒种子都能开花,但播下种子就比荒芜的旷野强百倍🏋

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

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

相关文章

Move 合约部署踩坑笔记:如何解决 Sui 客户端发布错误Committing lock file

Move 共学活动:快速上手 Move 开发 为了帮助更多开发者快速了解和掌握 Move 编程语言,Move 共学活动由 HOH 社区、HackQuest、OpenBuild、KeyMap 联合发起。该活动旨在为新手小白提供一个良好的学习平台,带领大家一步步熟悉 Move 语言&#…

【C语言】野指针问题详解及防范方法

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C语言 文章目录 💯前言💯什么是野指针?💯未初始化的指针代码示例问题分析解决方法 💯指针越界访问代码示例问题分析解决方法 💯指向已释放内存的…

关于如何在k8s中搭建一个nsfw黄图鉴定模型

随着现在应用内图片越来越多,安全审查也是必不可少的一个操作了 下面手把手教你如何将huggingface中的黄图检测模型部署到自己的服务器上去 1.找到对应的模型 nsfw_image_detection 2.在本地先验证如何使用 首先安装transformers python库 pip install transform…

初学 flutter 环境变量配置

一、jdk(jdk11) 1)配置环境变量 新增:JAVA_HOMEC:\Program Files\Java\jdk-11 //你的jdk目录 在path新增:%JAVA_HOME%\bin2)验证是否配置成功(cmd运行命令) java java -version …

信息安全实验--密码学实验工具:CrypTool

1. CrypTool介绍💭 CrypTool 1的开源教育工具,用于密码学研究。通过CrypTool 1,可以实现加密和解密操作,数字签名。CrypTool1和2有很多区别的。 来源于:网络安全快速入门5-密码学及密码破解工具CrypTool实战_百度知道…

服务器数据恢复—raid5阵列+LVM+VXFS数据恢复案例

服务器存储数据恢复环境: 某品牌MSA2000FC存储中有一组由7块盘组建的RAID5阵列,另外还有1块硬盘作为热备盘使用。 基于RAID5阵列划分的几个LUN分配给小机使用,存储空间通过LVM管理,重要数据为Oracle数据库及OA服务端。 服务器存储…

基于微信小程序的酒店客房管理系统+LW示例参考

1.项目介绍 系统角色:管理员、员工、普通用户功能模块:员工管理、用户管理、客房管理、预订管理、商品管理、评价管理、续订管理、订单管理等技术选型:SSM,vue,uniapp等测试环境:idea2024,jdk1…

学习Zookeeper

Zookeeper有手就行 1. 初识ZooKeeper1.1 安装ZooKeeper1.2 ZooKeeper命令操作1.2.1 Zookeeper数据模型1.2.2 Zookeeper 服务端常用命令1.2.3 Zookeeper客户端常用命令 2. ZooKeeperJavaAPl操作2.1 Curator介绍2.2 CuratorAPI常用操作2.2.0 引入Curator支持2.2.1 建立连接2.2.2 …

java基础知识(Math类)

引入:Math 类包含用于执行基本数学运算的方法,如初等指数、对数、平方根 import java.util.Math 1.abs绝对值 int abs Math.abs(-9); 2.pow求幂 double pow Math.pow(2,4); 3.向上取整 double ceil Math.ceil(3.9);//ceil 4 4.向下取整 dou…

【AIGC】大模型面试高频考点-RAG中Embedding模型选型

【AIGC】大模型面试高频考点-RAG中Embedding模型选型 (一)MTEB排行榜英文模型排名:1、bge-en-icl2、stella_en_1.5B_v53、SFR-Embedding-2_R4、gte-Qwen2-7B-instruct5、stella_en_400M_v56、bge-multilingual-gemma27、NV-Embed-v18、voyage…

学习threejs,使用设置normalMap法向量贴图创建更加细致的凹凸和褶皱

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.MeshPhongMaterial高…

SAP ME2L/ME2M/ME3M报表增强添加字段

SAP ME2L/ME2M/ME3M报表增强添加字段(包含:LMEREPI02、SE18:ES_BADI_ME_REPORTING) ME2L、ME2M、ME3M这三个报表的字段增强,核心点都在同一个结构里 SE11:MEREP_OUTTAB_PURCHDOC 在这里加字段,如果要加的字段是EKKO、…

dubbo-go框架介绍

框架介绍 什么是 dubbo-go Dubbo-go 是 Apache Dubbo 的 go 语言实现,它完全遵循 Apache Dubbo 设计原则与目标,是 go 语言领域的一款优秀微服务开发框架。dubbo-go 提供: API 与 RPC 协议:帮助解决组件之间的 RPC 通信问题&am…

不只是请求和响应:使用Fiddler抓包URL和Method全指南(中)

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持! 不只是请求和响应:使用Fiddler抓包HTTP协议全指南(上)-CSDN博客https://blog.csdn.net/Chunfeng6yugan/article/details/144005872?spm1001.2014.3001.5502 🙉在(上)篇博客中&#xf…

Linux操作系统学习---初识环境变量

目录 ​编辑 环境变量的概念: 小插曲:main函数的第一、二个参数 获取环境变量信息: 1.main函数的第三个参数 2.查看单个环境变量 3.c语言库函数getenv() 和环境变量相关的操作指令: 1.export---导出环境变量: 2.unse…

跨平台应用开发框架(1)----Qt(组件篇)

目录 1.Qt 1.Qt 的主要特点 2.Qt的使用场景 3.Qt的版本 2.QtSDK 1.Qt SDK 的组成部分 2.安装 Qt SDK 3.Qt SDK 的优势 3.Qt初识 1.快速上手 widget.cpp mian.cpp widget.h Helloworld.pro 2.对象树 3.坐标系 4.信号和槽 1. 信号和槽的基本概念 2. 信号和槽的…

mysql索引失效的五种情况

第一种 违反最左前缀法则 这个是针对联合索引的。 假设有个tb_seller表,现在给三个字段建立联合索引,建立的时候字段顺序不可随便设置,字段顺序: name, status, address。下图Seq_in_index对应的是联合索引顺序。 判断索引失效用…

H3C OSPF 多区域实验

目录 前言 实验拓扑 实验需求 实验解析 路由器配置 测试 前言 此篇文章为 OSPF多区域试验,建议先食用OSPF单区域实验,理解实验原理 学习基本配置,再来使用此篇,效果更佳!(当然如果你已经了解原理与基…

算法 Java实现

一.查找算法 1.分块查找 二.排序算法 1.冒泡排序

优先算法 —— 双指针系列 - 快乐数

1. 快乐数 题目链接: 202. 快乐数 - 力扣(LeetCode)https://leetcode.cn/problems/happy-number/description/ 2. 题目解析 示例1: 示例2: 3. 算法原理 两种情况:我们可以把两种情况都看作为循环&#xff0…