原文:
Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.
DEFINITION
Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list.
EXAMPLE
Input: A –> B –> C –> D –> E –> C [the same C as earlier]
Output: C
译文:
给定一个循环链表,实现一个算法返回这个环的开始结点。
定义:
循环链表:链表中一个结点的指针指向先前已经出现的结点,导致链表中出现环。
例子:
输入:A –> B –> C –> D –> E –> C [结点C在之前已经出现过]
输出:结点C
两个指针移动,fast是slow的两倍,如果存在环形,一定有相遇。例如两辆汽车,如果存在环形,快的一定会超慢的车。
如果在一个环形中,fast是slow的两倍,那么相遇时,fast一定比slow多走一圈。
假设在环形中距start的x步相遇,链表环形外有k个节点,环形中有n个节点,那么2(k+x)=k+n+x => x=n-k,所以相遇的位置距离start有k步。
代码部分,首先寻找相遇点,然后确保链表中存在环形,之后再将slow移到head处,slow和fast都按照一次1步移动,两者相遇即是start
public static LinkedListNode findStart(LinkedListNode head) {
LinkedListNode slow = head;
LinkedListNode fast = head;
while (fast != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
break;
}
}
if (fast.next == null) {
return null;
}
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return fast;
}
testcase:
public static void main(String args[]) {
LinkedListNode head = new LinkedListNode(0);
LinkedListNode node1 = new LinkedListNode(1);
LinkedListNode cyclestart = new LinkedListNode(2);
LinkedListNode node3 = new LinkedListNode(3);
LinkedListNode node4 = new LinkedListNode(4);
LinkedListNode node5 = new LinkedListNode(5);
LinkedListNode node6 = new LinkedListNode(6);
LinkedListNode tail = new LinkedListNode(7);
head.next = node1;
node1.next = cyclestart;
cyclestart.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = tail;
tail.next = cyclestart;
//output cyclestart, the data is 2.
System.out.println(findStart(head).data);
}