题目
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
Follow up:
Can you solve it without using extra space?
回环检测问题,参考维基百科http://en.wikipedia.org/wiki/Cycle_detection,发现有两种解法。
一种的Floyd提出的经典的龟兔(Tortoise and Hare)算法,另一种是Brent提出的改进算法,性能上有明显的提升。
通过LeetCode测试结果来看,Brent提出的算法性能确实更好。
每个算法的前半部分都是用来判断是否有环的,可以用来解答Linked List Cycle
代码
public class LinkedListCycleII {
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public ListNode detectCycle(ListNode head) {
// return floydAlgorithm(head);
return brentAlgorithm(head);
}
private ListNode brentAlgorithm(ListNode head) {
if (head == null || head.next == null) {
return null;
}
int power = 1;
int lam = 1;
ListNode tortoise = null;
ListNode hare = head;
while (hare != tortoise) {
if (hare == null) {
return null;
}
if (power == lam) {
tortoise = hare;
power *= 2;
lam = 0;
}
hare = hare.next;
++lam;
}
hare = head;
tortoise = head;
for (int i = 0; i < lam; ++i) {
hare = hare.next;
}
while (hare != tortoise) {
tortoise = tortoise.next;
hare = hare.next;
}
return tortoise;
}
private ListNode floydAlgorithm(ListNode head) {
if (head == null || head.next == null) {
return null;
}
ListNode hare = head.next.next;
ListNode tortoise = head.next;
while (hare != tortoise) {
if (hare == null || hare.next == null) {
return null;
}
hare = hare.next.next;
tortoise = tortoise.next;
}
tortoise = head;
while (tortoise != hare) {
hare = hare.next;
tortoise = tortoise.next;
}
return tortoise;
}
}