一个非常有趣的问题——链表带环问题

目录

前言

一、为什么快指针每次⾛两步,慢指针⾛⼀步可以相遇,有没有可能遇不上

二、快指针⼀次⾛3步,⾛4步,...n步⾏吗?

 三、求环形链表中入环的节点


前言

        在学习链表的时候我发现一个一个非常有趣的问题链表带环,可能大部分人都知道使用快慢指针来解决链表带环问题

        快慢指针解决链表带环问题

        慢指针⼀次⾛⼀步,快指针⼀次⾛两步,两个指针从链表起始位置开始运⾏, 如果链表 带环则⼀定会在环中相遇,否则快指针率先⾛到链表的未尾

//链表带环
bool hasCycle(struct ListNode* head)
{
	if (head == NULL || head->next == NULL)
	{
		return false;
	}
	//快指针,一次走2步
	struct ListNode* k = head;
	//慢指针,一次走1步
	struct ListNode* m = head;
	while (k != NULL && k->next != NULL)
	{
		k = k->next->next;
		m = m->next;
		//相遇
		if (k == m)
		{
			return true;
		}
	}
	//跳出循环表示,未带环
	return false;
}

         题目链接

        141. 环形链表 - 力扣(LeetCode)


        那这里大家是否思考过一下这两个问题,或者是否会有一下这两个问题

        1、为什么快指针每次⾛两步,慢指针⾛⼀步可以相遇,有没有可能遇不上

        2、快指针⼀次⾛3步,⾛4步,...n步⾏吗?  

        这里先做一个总结

快指针每次⾛两步,慢指针⾛⼀步一定可以相遇

如果N是偶数,第⼀轮就追上了
如果 N是奇数,第⼀轮追不上,快追上,错过了,距离变成-1,即C-1,进⼊新的⼀轮追击
        C-1如果是偶数,那么下⼀轮就追上了
        C-1如果是奇数, 那么就永远都追不上

 

一、为什么快指针每次⾛两步,慢指针⾛⼀步可以相遇,有没有可能遇不上

        假设slow也⾛完⼊环前的距离,准备进环,此时fast 和slow之间的距离为N,接下来开始追逐

 

        因为 fast 一次走2步, slow 一次走1步,相差1步,追逐过程中,每追击⼀次,他们之间的距离缩⼩1步

        追击过程中fast和slow之间的距离变化:

        fast和slow之间的距离:N

        fast和slow之间的距离:N - 1

        fast和slow之间的距离:N - 2

        fast和slow之间的距离:N - 3

        fast和slow之间的距离:N - 4

        fast和slow之间的距离:N - 4

        fast和slow之间的距离:........

        fast和slow之间的距离:N - N

        fast和slow之间的距离:0

        因此快指针每次⾛两步,慢指针⾛⼀步一定可以相遇

 

二、快指针⼀次⾛3步,⾛4步,...n步⾏吗?

        假设头节点到入环的距离为L,环的周长为C,slow也⾛完⼊环前的距离,准备进环,此时fast 和slow之间的距离为N,fast 和slow之间的相差距离为C - N,接下来开始追逐 

 

        按照上⾯的分析,fast 一次走3步, slow 一次走1步,相差2步,追逐过程中,每追击⼀次,他们之间的距离缩⼩2步 

         追击过程中fast和slow之间的距离变化:

        情况一:                                                       情况二:

        fast和slow之间的距离:N                           fast和slow之间的距离:N

        fast和slow之间的距离:N - 2                      fast和slow之间的距离:N - 2

        fast和slow之间的距离:N - 4                      fast和slow之间的距离:N - 4

        fast和slow之间的距离:N - 6                      fast和slow之间的距离:N - 6

        fast和slow之间的距离:N - 8                      fast和slow之间的距离:N - 8

        fast和slow之间的距离:N - 10                    fast和slow之间的距离:N - 10

        fast和slow之间的距离:........                      fast和slow之间的距离:..........

        fast和slow之间的距离:N - N                      fast和slow之间的距离:N - N - 1

        fast和slow之间的距离:0                            fast和slow之间的距离:-1

        fast和slow之间的距离为-1时,意味着fast反超了slow,进入了新一轮的追逐,此时fast和slow之间的距离为C - 1,( C为环的周长 )

        当fast于slow进入新的一轮追逐时C-1如果是偶数,那么下⼀轮就追上了,C-1如果是奇数, 那么就永远都追不上,这里我们用公式证明 

        在追逐过程中,慢指针到入环点时所⾛的路径⻓度:

        fast: L + xC + C - N( x 表示快指针在环中走了 x 圈)

        ( 节点到入环的距离 + fast在环中走了多少圈 + fast 和slow之间的相差距离 )

        slow:L

        ( 节点到入环的距离

        由于慢指针⾛⼀步,快指针要⾛三步,因此得出: 3 * 慢指针路程 = 快指针路程 ,即: 

        3L = L + xC + C - N

        2L = (x + 1)C - N

        由于偶数乘以任何数都为偶数,因此 ⼀定为偶数,则可推导出可能得情况:

        情况1:偶数 = 偶数 - 偶数
        情况2:偶数 = 奇数 - 奇数
结论
        如果N是偶数,则第⼀圈快慢指针就相遇了
        如果N是奇数,则fast指针和slow指针在第⼀轮的时候套圈了,开始进⾏下⼀轮的追逐;当N是奇数,要满⾜以上的公式,则 (x+1)C 必须也要为奇数,即C为奇数

         快指针⼀次⾛4、5.....步最终也会相遇,其证明⽅式同上

 

 三、求环形链表中入环的节点

        这个问题也是环形链表中一个非常经典的问题,同样的也是通过使用快慢指针来解决,快指针一次走2步,慢指针一次走1步,首先给出结论

         快慢指针的相遇点 于 头节点 到入环的距离是相等的

//寻找快慢指针的相遇点
struct ListNode* search(struct ListNode* head)
{
    struct ListNode* m = head;
    struct ListNode* k = head;
    while (k != NULL && k->next != NULL)
    {
        m = m->next;
        k = k->next->next;
        if (k == m)
        {
            return k;
        }
    }
    return NULL;
}
struct ListNode* detectCycle(struct ListNode* head)
{
    //寻找快慢指针的相遇点
    struct ListNode* meet = search(head);
    if (meet == NULL)
    {
        return NULL;
    }
    //快慢指针的相遇点 与 头节点 到入环的距离是相等的
    struct ListNode* m = head;//头节点
    struct ListNode* k = meet;//相遇点
    //相遇点与头节点同时向前走,直到相遇为止
    
    while (k != m)
    {
        m = m->next;
        k = k->next;
    }
    return k;
}

          题目链接 

         142. 环形链表 II - 力扣(LeetCode)


 

        证明 

        假设头节点到入环的距离为L,环的周长为C,slow也⾛完⼊环前的距离,准备进环,此时fast 和slow之间的距离为 C - N,fast 和slow之间的相差距离为N

        当慢指针相遇时所⾛的路径⻓度:

        fast: L + xC + N( x 表示快指针在环中走了 x 圈)

        ( 节点到入环的距离 + fast在环中走了多少圈 + fast 和slow之间的相差距离 )

        slow:L + N

        ( 节点到入环的距离 + fast 和slow之间的相差距离 

【注意】

        当慢指针进⼊环时,快指针可能已经在环中绕了x圈了,x⾄少为1

        慢指针进环之后,快指针肯定会在慢指针⾛⼀圈之内追上慢指针

        由于慢指针⾛⼀步,快指针要⾛两步,因此得出: 2 * 慢指针路程 = 快指针路程 ,即:  

        2(L + N) = L + xC + N

        L + N = xC

        L = xC - N

        L = (x - 1)C + C - N

        (x为1,2,3,4......,x的⼤⼩取决于环的⼤⼩,环越⼩x越⼤)

        取极端情况表示快指针在环中走了 1 圈,即 x = 1

        L = C - N

        1、L为头节点到入环点的距离

        2、C - N为fast 和slow之间的距离,即相遇点到入环的距离

        由此可以证明:快慢指针的相遇点 于 头节点 到入环的距离是相等的

       

       

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

重生之我爱上了k8s!

内容不全,待补充中...... 目录 一、k8s的部署 1.1.集群环境初始化 1.1.1.所有主机禁用swap 1.1.2.安装k8s部署工具 1.1.2.所有节点安装cri-docker 1.1.3.在master节点拉取K8S所需镜像 1.1.4.集群初始化 1.1.5.其他两台主机加入集群 1.1.6.安装flannel网络…

UE4 材质学习笔记12(水体反射和折射)

一.水体反射和折射 首先就是要断开所有连接到根节点的线,因为水有很多不同的节点成分,当所有其他节点都在用时 要分辨出其中一个是何效果是很难的。 虚幻有五种不同的方法可以创建反射,虚幻中的大多数场景使用多种这些方法 它们会同时运作。…

串口头汇总

1 网线头 1 4对应485A , 2 5对应485B ,1 4 接在一起,2 5 接在一起转成2根线也可以。 ----------拓展中

简单介绍冯诺依曼体系

现代的计算机, 大多遵守冯诺依曼体系结构 CPU中央处理器:进行算术运算和逻辑判断。存储器:分为外存和内存,用于存储数据(使用二进制方式存储)。输入设备:用户给计算机发号施令。输出设备:计算机…

【记录】Android|安卓平板 猫游戏(四款,peppy cat,含下载教程和链接)

前言 网上大部分直接找到的都是 iPad 的猫游戏,安卓的要查英文才找得到,但质量也都一般,或不知道在哪里下载。 遂自己找。 下载测试时间:2024/10/20 文章目录 前言1 检索2 亲测2.1 ✅⭐⭐⭐⭐⭐Cat Alone 1 and 22.2 &#x1f4…

Qt中使用线程之moveToThread

步骤: 1、创建一个自定义Worker类,继承自QObject 2、主线程中创建QThread的对象,Worker类的对象 3、Worker类的对象调用moveToThread函数移动到QThread的对象中 4、主线程自定义一个信号,并使用信号槽连接到worker类对象的任务…

身份和访问管理平台(IAM)是数字身份管理的关键路径和重要方法

随着数字化转型不断推进,越来越多的企业选择通过身份和访问管理平台(IAM)来管理数字身份。IAM不只是传统的账号、认证、授权、审计产品,更是数字身份管理的创新领航者,以权威数字身份为基础,结合用户与数字…

Python爬取京东商品信息,详细讲解,手把手教学(附源码)

Python 爬虫爬取京东商品信息 下面我将逐一解释每一部分的代码 导入库 from selenium import webdriver from selenium.webdriver.edge.service import Service from selenium.webdriver.edge.options import Options import time import random import csv from selenium.c…

VMware中Ubuntu安装

VMware官网:https://www.vmware.com/products/desktop-hypervisor/workstation-and-fusion 先在官网下载VMware,一直根据默认点下一步就好了,记得更改安装地址哦,否则默认下在C盘里。 先下载好Ubuntu映像文件:https://…

[电子科大]王丽杰 离散数学 第二讲 特殊集合和集合间关系 笔记

1.2 特殊集合与集合间关系 空集 不含任何元素的集合叫做空集(empty set),记作∅. 空集可以符号化为 ∅ { x ∣ x ≠ x } ∅ \{ x|x ≠ x\} ∅{x∣x​x} . 空集是绝对唯一的。 全集 针对一个具体范围,我们考虑的所有对象的集合叫做全集(universal …

JMeter模拟并发请求

PostMan不是严格意义上的并发请求工具,实际是串行的,如果需要测试后台接口并发时程序的准确性,建议采用JMeter工具。 案例:JMeter设置20个并发卖票请求,查看后台是否存在超卖的情况 方式一:一共10张票&…

视觉分析在烟火检测中的应用

随着城市化进程的加快,烟火安全问题日益突出。传统的烟火检测方式依赖人工巡查和基础传感器,容易受到人为因素和环境条件的影响,导致检测效率低下和误报率高。为了解决这一问题,烟火检测算法的引入为我们提供了一种全新的解决方案…

前端根据某数组是否有数据渲染按钮

代码:React TypeScript 由于这个data可能是undefined,所以报错了,问了chatgpt,可以进行的检查方式有以下几种: 1、使用可选链 或者这样写: 我个人比较喜欢用第二种,因为比较简洁 2、类型守卫…

python中使用库pandas来创建excel表格

先需要pip或者conda下载这个pandas 源码如下: import pandas as pdsList_1 [1,2,3,4,5] List_2 [软件,硬件,结构,产品经理,项目经理] List_3 [杭州,南京,河南,合肥,成都] List_4 [21,22,23,24,25] List_5 [2000,3000,1400,1500,2000]TitleData { # 用字典设…

KUKA机器人选定程序时提示“选择非法”的处理方法

KUKA机器人选定程序时提示“选择非法”的处理方法 如下图所示,选中某个程序,点击选定时, 系统提示:选择非法, 具体处理方法可参考以下内容: 选中该程序后,在右下角打开【编辑】菜单键,再选择【属性】,打开后可以看到程序的一般说明、信息模块和参数等信息,如下图所示…

ERP、SCM与CRM:三大系统的区别与整合策略

ERP(企业资源规划)、SCM(供应链管理)和CRM(客户关系管理)系统的关系与区别可以概括为:ERP整合企业内部资源和流程,SCM优化供应链环节,CRM关注客户关系和销售管理。这三个…

[前端] ✨【如何用课程设计提升工程能力?】✨笔记

✨【如何用课程设计提升工程能力?】✨ 📚 课程设计真的在语言工具类课程中占据了“C位”!👑设计得好的课程简直像一个实战训练营,既能帮助学生巩固理论,又能培养解决复杂问题的能力,还能让他们…

13_渲染器的设计

目录 渲染器与响应式系统的结合渲染器的基本概念自定义渲染器 渲染器与响应式系统的结合 渲染器与响应式系统是相辅相成的,渲染器负责将响应式系统中的响应式数据渲染到视图中,而响应式系统则负责监听数据的变化并通知渲染器进行更新。 渲染器在浏览器…

第13篇:无线与移动网络安全

目录 引言 13.1 无线网络的安全威胁 13.2 无线局域网的安全协议 13.3 移动通信中的安全机制 13.4 蓝牙和其他无线技术的安全问题 13.5 无线网络安全的最佳实践 13.6 总结 第13篇:无线与移动网络安全 引言 无线和移动网络的发展为我们的生活带来了极大的便利…

爱快路由器配置腾讯云动态域名DDNS详细说明

直白点说就是让爱快路由器自动配置当前公网IP地址给域名,动态域名DDNS不清楚的请自行百度, 这里就可以看见操作日志,那么我们一步一步来配置它吧,首先登录爱快路由器,如下图: 那么腾讯云我们怎么找到ID和…