环形链表Ⅱ
题目
给定一个链表的头节点 head
,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
。
不允许修改链表。
示例1:
1
2
3输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。示例2:
1
2
3输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。示例3:
1
2
3输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环
进阶:
- 使用
O(1)
空间解决此题
思路+代码
本题可以采用哈希表与快慢指针的方式分别完成解题
哈希表实现算法
- 通过遍历链表中的每个节点,并将节点存储在哈希表中
- 当出现加入的节点已经存在哈希表中,就可以判定链表中存在环,否则表明链表没有环
代码实现:
1 |
|
快慢指针实现算法
通过设定两个指针 fast
和 slow
,均位于链表头部。slow
指针每次移动一位,fast
指针每次移动两位,如果链表中存在环,则 fast
指针最终会追赶上 slow
指针并在环中相遇
假设链表有环,会有两种环情况:
- 环很大
假如他们在相遇点相遇了,那么慢指针走过的距离是 a+b
,快指针走过的距离就是 a+b+c+b
。因为相同时间内快指针走的距离是慢指针的 2
倍,所以有 a+b+c+b = 2*(a+b)
,即 a=c
,也就是说从相遇点到环的入口和链表的起始点到环的入口,距离是一样的。在相遇点的时候我们可以使用两个指针,一个从相遇点开始,一个从链表头开始,他们每次都走一步,直到他们再次相遇位置,那么这个相遇点就是环的入口。
- 环很小
那么这种情况,快指针在环上转了好几圈了,慢指针才走到环上,假如快指针在环上已经走了 m
圈了,慢指针在环上走了 n
圈,他们最终在环上相遇,那么
- 慢指针走过的距离是:
a+b+n*(b+c)
(b+c其实就是环的长度) - 快指针走过的距离是:
a+b+m*(b+c)
在相同的时间内快指针走过的距离是慢指针的2倍,所以有 a+b+m*(b+c) = 2*(a+b+n*(b+c))
整理得到a+b=(m-2n)(b+c)
上面b+c
其实是环的长度,也就是说a+b
等于(m-2n)
个环的长度。这个时候我们还可以使用两个指针一个从相遇点开始,一个从链表头开始,这时候就会出现一个现象就是一个指针在链表上走,一个指针在环上转圈,最终会走到第1
种情况,就是环很小(我们可以认为链表前面减去m-2n-1
个环的长度就是第一种情况了)
代码实现:
1 |
|
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/linked-list/jjhf6/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者: 贾明晖
本文链接: http://minghuijia.cn/2022/03/31/%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8%E2%85%A1/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!