链表中环的入口结点
题目:
给出一个链表,找出该链表中环的入口结点。
示例:
该链表中环的入口结点是 2
思路:
① 判断链表是否为空或是否只有一个结点。
② 定义两个快慢指针,分别记作:fast、slow。每次让fast向前走两步,slow向前走一步。
③ 若fast和slow相遇,则说明链表中存在环,记相遇结点为meetNode。
④ 定义一个tmp引用,从链表的第一个结点出发,让tmp、meetNode以相同步长向前走,当tmp==meetNode时,tmp、meetNode共同指向的结点就是链表中环的第一个结点。
证明:
X,Y,Z分别为链表起始位置,环开始位置和两指针相遇位置。慢指针的速度设为 x,则快指针的速度为2x。
快慢指针均从X出发,在Z相遇。此时,慢指针走的距离为:(a+b),快指针走的距离为: a+b+n(b+c)。
所以, (a+b)/x = a+b+n(b+c)/2x,化简得:2*(a+b) = a+b+n*(b+c)
推出:a = (n-1)b+nc = (n-1)(b+c)+c
即将此两指针分别放在起始位置和相遇位置,并以相同速度前进,当一个指针走完距离a时,另一个指针恰好走出 n-1圈加c的距离。
代码实现:
public class Solution {
public ListNode isCycle(ListNode head){
if(head==null || head.next==null){
return null;
}
ListNode slow = head;
ListNode fast = head;
while(slow!=null && fast!=null && fast.next!=null){
slow = slow.next;
fast = fast.next.next;
if(slow == fast){
return slow;
}
}
return null;
}
public ListNode detectCycle(ListNode head) {
ListNode meetNode = isCycle(head);
ListNode tmp = head;
if(meetNode != null){
while(tmp!=meetNode){
tmp = tmp.next;
meetNode = meetNode.next;
}
return meetNode;
}
return null;
}
}