LeetCode-142 环形链表 II
LeetCode-142 环形链表 II
题目描述
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
如果链表中有某个节点,可以通过连续跟踪 next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos
来表示链表尾连接到链表中的位置(索引从 0
开始)。如果 pos
是 -1
,则在该链表中没有环。注意:pos
不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
数据样例
示例 1:
1 | 输入:head = [3,2,0,-4], pos = 1 |
示例 2:
1 | 输入:head = [1,2], pos = 0 |
示例 3:
1 | 输入:head = [1], pos = -1 |
提示:
- 链表中节点的数目范围在范围 $[0, 10 ^ 4]$ 内
- $-10 ^ 5 \leq Node.val \leq 10 ^ 5$
pos
的值为-1
或者链表中的一个有效索引
进阶:你是否可以使用 $O(1)$ 空间解决此题?
快慢指针 - $O(N)$
这个题目快慢指针思路巧妙
快慢指针相遇
- 使用两个指针(快慢指针):移动速度快的指针叫做
fast
, 慢的指针叫做slow
slow
:从起点head
出发,每次链表方向上移动 $1$ 个位置fast
:从起点head
出发,每次链表方向上移动 $2$ 个位置
快慢指针移动过程如下图所示:
- 相遇点 和 环入口点 上方距离为 $b$,下方距离为 $c$
- 快慢指针一定会在环内相遇
相遇时,两个指针的移动距离:
- 快指针移动距离 $L_f$:假设相遇前快指针在环上移动了 $n$ 圈,之后移动至相遇点。
$$L_f = a + n * (b + c) + b$$ - 慢指针移动距离 $L_s$:从环入口点开始移动至相遇点
$$L_s = a + b$$
寻找环入口点
由于 两个指针经过相同的时间,快指针速度是慢指针速度的两倍,因此 移动的距离也是两倍关系:
$$
L_f = 2 * L_s \Rightarrow a + n * (b + c) + b = 2 * (a + b)
$$
通过计算我们得到关系:
$$
a = (n - 1) * (b + c) + c
$$
快慢指针相遇时发现:
- 此时
slow
指针在 距离环入口点 $c$ 距离的位置(也就是相遇点位置) - 我们额外使用一个指针
ptr
,从起点出发,那么此时其 距离环入口点 $a$ 距离的位置(也就是起点位置)
此时,如果 slow, ptr
同时开始 每次均移动 $1$ 个位置
由于 $a = (n - 1) * (b + c) + c$,可以得知:slow, ptr
相遇点就是环入口点
时间复杂度 - $O(N)$
- 慢指针
slow
会走到相遇点,因此走过的长度不会超过链表总长度:$O(N)$ ptr
指针最后会走到环入口点,因此其走过的长度也不会超过链表总长度:$O(N)$
因此整体时间复杂度为:$O(N)$
空间复杂度 - $O(1)$
- 仅使用了若干个指针
代码
1 | /** |
1 | /** |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Cat's Blog!
评论