Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
Constraints:
-
The number of the nodes in the list is in the range [0, 104].
-
-10⁵ <= Node.val <= 10⁵
-
pos is -1 or a valid index in the linked-list.
方法一:《剑指Offer》No.23的解法
-
查 - 查看是否存在环,有环的得出快慢指针相遇时所处在节点,进行下一步,没环的直接返回。这用到快慢双指针算法,具体内容可查看LeetCode - Easy - 141. Linked List Cycle。
-
量 - 测量环节点个数n。
-
走 - 双指针指向头指针,一指针先走n步,然后两指针齐步走,两指针相等的位置,则环的入口点。
方法二:LeetCode优秀的回答
When fast and slow meet at point p, the length they have run are ‘a+2b+c’ and ‘a+b’.
Since the fast is 2 times faster than the slow. So a+2b+c == 2(a+b), then we get ‘a==c’.
So when another slow2 pointer run from head to ‘q’, at the same time, previous slow pointer will run from ‘p’ to ‘q’, so they meet at the pointer ‘q’ together.
import com.lun.util.SinglyLinkedList.ListNode;
public class LinkedListCycleII {
//方法一:《剑指Offer》的解法
public ListNode detectCycle1(ListNode head) {
ListNode collision = hasCycle(head);
if (collision != null) {
int cycleLength = count(collision);
ListNode p1 = head;
ListNode p2 = head;
while (cycleLength-- > 0) {
p2 = p2.next;
}
while (p1 != p2) {
p1 = p1.next;
p2 = p2.next;
}
return p1;
}
return null;
}
// 判断是否存在环
private ListNode hasCycle(ListNode head) {
ListNode walker = head;
ListNode runner = head;
while (runner != null && runner.next != null) {
walker = walker.next;
runner = runner.next.next;
if (walker == runner)
return walker;
}
return null;
}
// 计算环有多少节点
private int count(ListNode p1) {
int count = 1;
ListNode p = p1.next;
while (p != p1) {
count++;
p = p.next;
}
return count;
}
//方法二:leetcode优秀回答
public ListNode detectCycle2(ListNode head) {
ListNode fast = head, slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
ListNode slow2 = head;
while (slow != slow2) {
slow2 = slow2.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
}
import static org.junit.Assert.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
import com.lun.util.SinglyLinkedList.ListNode;
public class LinkedListCycleIITest {
@Test
public void test() {
LinkedListCycleII obj = new LinkedListCycleII();
ListNode node1 = new ListNode(3), node2 = new ListNode(2),
node3 = new ListNode(0), node4 = new ListNode(-4);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node2;
assertEquals(node2, obj.detectCycle1(node1));
assertEquals(node2, obj.detectCycle1(node2));
}
@Test
public void test2() {
LinkedListCycleII obj = new LinkedListCycleII();
ListNode node1 = new ListNode(1), node2 = new ListNode(2);