快慢双指针,一探环形链表的奥秘
一、原题描述
原题传送门
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:

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

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

输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
二、思路分析(重点)
本题的两个主要思考点是:
1.判断链表是否有环
2.如果有环,那如何找到这个环的入口
思考一:链表是否有环(双指针思路)
- 有做过这道题目的小伙伴应该都想到双指针这个思路,定义两个快慢指针,如果两个指针在移动过程中相遇了,说明此链表有环,如果快慢指针一直移动但是不相遇,则表明此链表一定没有环
- 因为我们就选择去定义一个快指针fast和一个慢指针slow,既然说是快慢指针,则表示它们移动的速度一定是不同的,我们让快指针每次移动两个结点,慢指针每次移动一个结点,这么定义其实就是为了实现让快指针在环中去追赶慢指针的一个动作,但是有些小伙伴就比较疑惑一个点?
快慢指针一定会相遇吗?难道快指针在移动的过程中就不会错过慢指针吗? - 答案是:是的,它们一定会相遇,因为快指针就比慢指针每次多走一格,它是在一个结点一个结点地去靠近慢指针。但如果快指针每次走的步数是三个结点,那就不一定了,可能会出现错位
先粗略地画一下,大概是这么个结构(比较丑凑合着看👺)

思考二:如果有环,怎么找到环的入口(数学思维)
- 假设此刻我们已经知道了这个链表一定是有环的,那么我们怎么去找到这个环形的入口结点呢,这就需要用到数学的思维了🎓
- 我们设头结点到环形入口结点的距离为x
- 入口结点到快慢指针相遇点的距离为y
- 然后从这个相遇点再回到环形点的入口为z
- 大致结构如下图所示👇

- 这里的需要根据快慢指针的每次的移动距离去确定一个等式,
慢指针:x + y 每次移动一步
快指针:x + y + n(y + z) 每次移动两步
2(x + y) = x + y + n(y + z)
- 消去一个x + y可以得到
x + y = n(y + z)
- 由题目意思可以知道,要我们求的是链表入环的第一个结点,因此就是我们设的这段x距离,所以我们把y移到右边
x = n(y + z) - y
- 但是这样子我们看不出x和什么正数有关系,因此想到让出一圈的距离,将n变为(n - 1),然后配好后面的关系,可以得到如下关系式
x = (n - 1) (y + z) + z
- 从如上表达式我们就可以看出x和z是有着关系的,这里的n一定是>=1的,因为快指针不可以再第一圈的时候就和慢指针相遇,上面有提到快指针它是在追赶慢指针的一个过程,所以一定是在慢指针进入环内,然后快指针在饶了1圈或n圈后,才环内的某一个结点相遇的,这里当n = 1是,等式就变成了
x = z
- 这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点
- 此处就是标题说到的第二重双指针了,设

本文详细解析了如何使用快慢双指针判断链表中是否存在环,并找到环的入口节点。首先,通过快慢指针判断链表有无环,之后利用数学推理确定环的入口。在快慢指针相遇后,设置新的双指针从相遇点和头节点同时开始,直至相遇即为环形入口。此外,文章还探讨了其他解法,如哈希表。
最低0.47元/天 解锁文章
769

被折叠的 条评论
为什么被折叠?



