链表关键:头指针无前向指针,故引入dummy_head作为一定存在的头指针
如何获取位置?就像在操场跑步如何遇见彼此,有一定的差速即可
需处理结点前方的指针,故诞生慢指针,以作出操作,而快指针用于搜索
链表删除操作中,若找到待删结点的前一个结点,应该一直尝试围绕此结点删除,而不是删除后遍历至下一个结点
因为遍历至下一个节点时已经无法删除下一个结点,而下一个节点正好可能是需要删除的节点
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
* 为什么采用快慢指针而不是记录开头遍历?因为链表环路是局部的
* 为什么当快指针只比慢指针移速快1的时候它们必定相遇?因为环的大小至少为1,不可能产生跳跃(快2、3时就可能出现溢出不相遇问题,比如如果环长为2,快指针快2
* ,可能出现快慢指针相对不动)
* n即圈差,快指针能追上慢指针是因为套圈了(>=1,刚好在慢指针进入时快指针转一圈则为快1圈,多出来的是因为快指针到时慢指针还没到,都在环内时,
* 快指针追上慢指针因为差速为一至多环大小次,即多转一圈,或者说当慢指针要走到一圈时,快指针早快走完两圈,早已与它相遇)
*/
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast=head,slow=head,index1=head,index2;
if(head==null) return null;
//假设入口离头节点x,相遇时离入口y,差入口z,追圈时多走了n圈,fast走了n(y+z)+x+y,slow走了x+y,同时开始走,
//则2(x+y)==n(y+z)+x+y,即x==z+(n-1)(x+y)==z(圈数被整除,无意义)
while(fast.next!=null&&fast.next.next!=null)
{
fast=fast.next.next;
slow=slow.next;
if(slow==fast)
{
index1=fast;
index2=head;
while(index1!=index2)
{
index1=index1.next;
index2=index2.next;
}
return index1;
}
}
return null;
}
}