142. 环形链表 II
题目链接: https://leetcode.cn/problems/linked-list-cycle-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 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
提示:
- 链表中节点的数目范围是 [0, 104]
- -105<= Node.val <= 105
pos
为-1
或者链表中的一个 有效索引 。进阶: 你是否可以使用 O(1) 空间解决此题?
解题思路分析
根据题目,我们可以把题目分成两个问题分析
- 如何判断是否有环
- 如果有环如何返回链表开始入环的第一个节点
1.如何判断是否有环
这个问题在之前的环形链表Ⅰ文章中已经详细分析过了。
感兴趣的话点击链接:http://t.csdnimg.cn/zmymE
2.如果有环,如何返回链表开始入环的第一个节点
我们画图进行分析
我们假设:
- 入口点到环入口点为:
L
- 入口点到相遇点为:
X
- 环的长度:
C
- 那么从开始到相遇时
slow
走的距离为:L+X
- 当
slow
还没有进入环中L
足够大时,fast
在环中已经走了n
圈 - 那么从开始到相遇时
fast
走的距离为:L+n*C+X
fast路程=slow路程*2
2*(L+X)=L+n*C+X
L+X=n*C
L=n*C-X
通过上面分析,得出结论:
- 我们让一个指针从相遇点开始走,另一个指针在开始点开始走
- 那么两个指针会在环的入口点相遇
(这块比较难理解,如果不理解的话可以自己画图分析一下)
这时我们就解决了找环的入口的问题!
代码
附代码:
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast&&fast->next)
{
slow=slow->next;//一步
fast=fast->next->next;//两步
if(slow==fast)//相遇
{
//让cmp从相遇点开始走
struct ListNode* tmp =slow;
//head从开始点开始走
while(head!=tmp)
{
head=head->next;
tmp=tmp->next;
}
return tmp;
}
}
return NULL;
}
※ 如果文章对你有帮助的话,可以点赞收藏!!谢谢支持