目录
一、前言:
该题是力扣141环形链表I的进阶,上一题的知识点这一题需要用到,因此还没做过上一题的先去做一下哦。
该博客有做题链接和算法讲解。
二、前置知识 :
同时从起点开始,快指针每次走两步、慢指针每次走一步,如若链表中有环,能在两节点都进环后,一圈以内相遇。
(这是结论,推导看:力扣141环形链表问题|快慢指针算法详细推理)
三、 算法推导
推导过程:
两指针在环中相遇时如下所示:
当慢指针进环前,快指针已经在环里至少n圈(n>=1),因为快指针走的更快,它们相遇时,肯定不是快指针第一次到达相遇点,至少已经到达过一次或更多次,再转回来。
由V快=2V慢 得 S快=2S慢
S慢=L+X
S快=L+X+nC
即: L+X+nC=2(L+X)
解得:L+X=nC
L=nC-X
L=(n-1)C+(C-X)
L=(n-1)C+(C-X)
如图,让指针Pa从head出发,一次走一步,
让指针Pb从相遇点出发,一次走一步,
同时走(C-X)步,
此时,Pb已到达入环点,而Pa还在路上。
再同时走(n-1)C步,
此时,Pa到达入环点,Pb因为走C的倍数,还是回到入环点,
两指针刚好在入环点相遇。
结论:
先用快慢指针法找到相遇点。
再让一个指针从起点出发,一个指针从相遇点出发,
同时走,每次走一步,相遇点就是入环点。
四、代码
这里的代码包含了上一道的快慢指针法,详细请看定上一道题的博客的讲解。
public class Solution {
//力扣142
//找带环链表中的入环节点
public ListNode detectCycle(ListNode head) {
//特殊情况处理
if (head == null || head.next == null) {
return null;
}
//定义快慢指针找相遇点
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null && slow != null) {
slow = slow.next;
fast = fast.next.next;
if (fast == slow) {
//找到相遇点
ListNode Pb = fast;//Pb从相遇点开始走
ListNode Pa = head;//Pa从起点开始走
while (Pa != Pb) {
Pa = Pa.next;
Pb = Pb.next;
}
return Pa;
}
}
return null;
}
}