环形链表问题

news/2024/11/15 7:28:26/

文章目录

  • 环形链表问题
    • 1.环形链表
      • 题干
      • 思路
      • 延申问题
      • 总结
    • 2. 环形链表 II
      • 题干
      • 思路


环形链表问题

环形链表就是一个链表没有结束的位置,链表的最后一个节点它会指向链表中的某一个节点形成一个环。

拿力扣的两到题目来看

1.环形链表

题干

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false

测试用例1

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

测试用例2

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

思路

快慢指针,如果链表是有环的那么它必然不会结束。定义一个快指针fast和一个慢指针slowfast一次走2步,slow一次走1步,如果没有环fast就会走到NULL,如果有环fast就会追上slow

在这里插入图片描述

代码

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

延申问题

  1. 为什么slow走一部,fast走两步,它们一定会再环里相遇,会不会永远追不上?

    不会出现追不上的情况,如果链表又换是一定能追上的。假设slow进环的时候,fast和slow的距离是NNN,紧接着追击的过程中,fast往前走两步,slow走一步,它们每走一次,它们之间的距离都是缩小1的。

    NNN

    N−1N-1N1

    N−2N-2N2

    .........

    222

    111

    000,距离缩小到0的时候就会相遇。

在这里插入图片描述

  1. slow走1步,fast走3步?走4步?走n步行不行?

    假设slow进环的时候,fast和slow的距离是NNN,接着进行追击的时候,fast向前走3步,slow向前走1步,它们每走一次,它们之间的距离缩小2。那么就会分为两种情况。

    假设红色部分是slow入环,fast和slow的距离

在这里插入图片描述

1.如果NNN为偶数

假设红色部分距离为10,也就是说距离N=10N = 10N=10,再追击过程中,fast走3步slow走1步,它们的距离是每次缩小2的。

101010

10−210-2102

10−410-4104

.........

222

000

如果NNN为偶数,fast走3步slow走一步是可以相遇的

2.如果N为奇数

假设红色部分距离为11,也就是说距离N=11N = 11N=11,再追击过程中,fast走3步slow走1步,它们的距离是每次缩小2的。

111111

11−211-2112

11−411-4114

.........

11−1011-101110

−1-11 ,当距离为−1-11的时候fast和slow的差距就变成了C−1C-1C1,CCC为环的长度。那么这个时候C−1C-1C1恰好也是奇数,那么fast就永远也追不上slow了

总结

fast走多步,slow走一步时不可行的。

如果slow进环时,上图红色部分的距离也就是fast要追slow的距离NNN为奇数,且环的长度为偶数,那么fast和slow就会一直在环里面打转,永远追不上。

如果距离NNN为奇数,环的长度为奇数,fast走多部则会出现跳过slow的情况,也可能会相遇的。

2. 环形链表 II

题干

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表

测试用例1

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

测试用例2

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。

思路

这一道题相较于上一道题的区别就是,一个判断是否有环一个时找到环的入口点。这就是上一个题目的一个变形。

  • 设起点道入口点的距离为XXX
  • 设相遇点道入口点的距离为YYY
  • 设环的大小为CCC

在这里插入图片描述

那么慢指针slow走的路程就是X+YX+YX+Y

快指针走的路程比较特殊,如果起点道入口的距离XXX比较长,而环的大小CCC又比较小,那么fast可能会在环里走好几圈,假设走了NNN圈,所以快指针fast走的路程为 X+Y+N∗CX+Y+N*CX+Y+NC

因为快指针fast走的路程是慢指针slow的2倍,所以最后的公式就是

2∗(X+Y)=X+N∗C+Y2*(X+Y) = X+N*C+Y2(X+Y)=X+NC+Y

化简之后就得出这么一个公式

X=N∗C−YX = N*C-YX=NCY

假设环比较大,fast刚走完一圈就和slow相遇那么N=1N = 1N=1,起点到入口点的距离就等于环的大小减去入口点到相遇点的距离。X=C−YX = C-YX=CY

那么当两个指针相遇时就可以将其中一个指向起点位置,让它们同时走一步,就会在入口点相遇。

代码实现

struct ListNode *detectCycle(struct ListNode *head) 
{if (head == NULL || head->next == NULL){return NULL;}struct ListNode* fast = head;struct ListNode* slow = head;while (fast != NULL && fast->next != NULL){fast = fast->next->next;slow = slow->next;if (fast == slow){fast = head;while (fast != slow){fast = fast->next;slow = slow->next;}return fast;}}return NULL;
}

题目来源力扣环形链表



http://www.ppmy.cn/news/4137.html

相关文章

我通过了软考高项,有些话想说

文章目录1. 软考成绩2. 备考过程与经验3. 遇到的坑4. 论文准备5. 资料及寄语1. 软考成绩 昨天下午得到了一个振奋人心的消息,我的软考通过了,感觉努力没有白费很欣慰,也感觉有很多话要说(真不是得瑟)。可能很多人不了…

戴尔r730xd服务器从u盘启动设置方法(戴尔r730取消网络启动方法)

1,开机后出现提示的时候,按F12 2,等一会系统会自动进入BIOS选择菜单:选择system bios 回车 3,这时在选择boot setting 回车: 4,在这里选择 BIOS Boot settings 5,将网卡启动的勾选去掉,即默认使用C盘启动 6,退出Esc,会提示保存&#xff0…

程序猿的福音——猿如意使用有感

猿如意介绍: 猿如意是一款面向开发者的辅助开发工具箱,包含了效率工具、开发工具下载,教程文档,代码片段搜索,全网博文搜索等功能模块。帮助开发者提升开发效率,帮你从“问题”找到“答案”。 猿如意的下…

selenium三大等待

使用场景:有时候当我们操作页面元素时,需要等待这个过程才能操作成功。 做Ui自动化的时候,考虑到稳定性:多次运行同一脚本,都能够保证它是成功的。 一、强制等待:sleep(秒) 比如sleep(10),就…

vue3表单输入绑定 v-model

vue3表单输入绑定 v-model 一、基本使用 1.1、v-model 使用 <template><input type"text" v-model"msg"/><h2>{{msg}}</h2> </template><script setup> import { ref} from vue const msgref("Hello World&quo…

数据结构专题(附完整代码)

文章目录1、绪论1.1 数据结构起源1.2 基本概念和术语1.3 抽象数据类型1.4 算法和算法分析2、线性表2.1 线性表的定义2.2 线性表的顺序存储结构和实现2.3 线性表的链式存储结构和实现2.4 顺序表和线性表的比较2.5 线性表的应用3、栈和队列3.1 栈3.2 队列3.3 表达式计算3.4 递归4…

Google Earth Engine(GEE)——如何加载影像并用remap重命名波段属性名称和可视化加载

本文的教程主要又两个方面一个时选择影像的加载,当然这里我们选择ESA10m全球分辨率土地分类数据,然后用remap函数完成对影像波段的重命名,最后设定一个可视化参数用于替代原来的影像色带实现土地影像色彩的重新加载。 数据集: The European Space Agency (ESA) WorldCove…

数据库的事务

作者&#xff1a;~小明学编程 文章专栏&#xff1a;MySQL 格言&#xff1a;目之所及皆为回忆&#xff0c;心之所想皆为过往 目录 什么是事务&#xff1f; 事务的特性 原子性 一致性 持久性 独立性 事务之间的影响 脏读 不可重复读 幻读 数据库的隔离级别 读未提交…