> 文章列表 > [LeetCode] 142. 环形链表 II

[LeetCode] 142. 环形链表 II

[LeetCode] 142. 环形链表 II

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

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。

注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

输入:head = [3,2,0,-4], pos = 1

输出:返回索引为 1 的链表节点

解释:链表中有一个环,其尾部连接到第二个节点。

解题思路:

主要是有两个两知识点:

  • 判断链表是否环
  • 如果有环,如何找到这个环的入口

1.判断链表是否有环

使用快慢指针法(双指针法)。

分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动2个节点,slow指针每次移动1个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表是有环的。

那么来看一下,为什么fast指针和slow指针一定会相遇呢?

这是因为fast是走两步,slow是走一步。那相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

2.如何找到这个环的入口

设fast指针走过的路程是f(f个节点),slow指针走过的路程是s(s个节点)。

因为fast是走两步,slow是走一步,他们相遇时候,那么f=2s。

fast和slow指针相遇时候,fast比slow走多了nb个节点(n表示的是n个环的)。

所以,f=s+nb;又因为f=2s;所以s=nb。

从上图看,要走到入环点,走 (a+nb) a 个节点就一定是到了入环点的。

因为相遇的时候,slow已经走了nb个节点,那再走a个节点就可以到了入环点。那我们是不知道a是多少步的嘛。

而这个,只要一个新指针从头节点 开始走a个节点,也到了入环点

那么只要一个新指针从头节点出发,slow指针从和fast指针相遇的节点出发,那相遇的时候就是入环点了。

这样就可以找到入环点了。

这是在力扣上别人的想法的,有点巧妙。

代码:

class Solution {
public:ListNode *detectCycle(ListNode *head) {if(head==nullptr)return head;auto fast=head;auto slow=head;while(fast && fast->next){fast=fast->next->next;slow=slow->next;if(fast==slow){auto index1=slow;auto index2=head;while(index1!=index2){index1=index1->next;index2=index2->next;}return index1;}}return nullptr;}
};