[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;}
};