**
环形链表的环长和入口求解
快慢双指针解法
求入口位置时,一个环形链表,我们假设链表的起始点到环的入口点的距离为L,环的周长为R,环的入口点到快慢指针的相遇位置的距离为X
快指针走的距离:F = L+X+nR
慢指针走的距离:S = L+X
因为快指针走的距离是慢指针的两倍,所以F = 2S。
这时:L+X+nR = 2 * (L + X)
L = nR - X
public class RollLinkedList {
public static void main(String[] args) {
Node n1 = new Node(1);
Node n2 = new Node(2);
Node n3 = new Node(3);
Node n4 = new Node(4);
Node n5 = new Node(5);
Node n6 = new Node(6);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = n6;
n6.next = n1;
System.out.println("环长"+findLoopLength(n1));
System.out.println("入口" + findLoopEnter(n1));
}
public static int findLoopLength(Node head) {
Node fast = head;
Node slow = head;
boolean loopExist = false;
int len = 1;
if (head == null) {
return 0;
}
//判断是否有环
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
loopExist = true;
System.out.println("链表有环");
break;
}
}
//求环长
if (loopExist) {
fast = fast.next;
while (slow != fast) {
fast = fast.next;
len++;
}
return len;
}
//链表没有环
return 0;
}
//环入口
public static int findLoopEnter(Node head) {
Node fast = head;
Node slow = head;
if (head == null) {
return 0;
}
//判断是否有环
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
System.out.println("链表有环");
//有环
//记住相遇点的指针,一个从相遇点开始,一个从头开始,相遇的地方就是环的入口点
Node tmp = head;
//假设链表的开始就是入口点
if (tmp == fast) {
return fast.value;
}
//如果入口不是在开始,则slow(temp)**从头**开始走l长度,
//fast从相遇点继续(并没有从头开始走哦)向前走nr-x长度,
//他们一定会在环入口处相遇
while (true) {
fast = fast.next;
tmp = tmp.next;
if (fast == tmp) {
break;
}
}
return fast.value;
}
}
return -1;
}
}
class Node {
public int value;
public Node next;
public Node(int data) {
this.value = data;
}
}
参考https://blog.youkuaiyun.com/baidu_40931662/article/details/84306202#commentBox
https://blog.youkuaiyun.com/weixin_42146769/article/details/88430572