第一种方法:直接遍历时,用hashset存放,判断是否存在环
第二种方法:使用快慢指针
public class CycleLinkedList {
public static void main(String[] args) {
Node head = new Node(1);
Node node3 = new Node(3);
head.next = node3;
head.next.next = new Node(5);
head.next.next.next = new Node(7);
head.next.next.next.next = new Node(9);
head.next.next.next.next.next = node3;
System.out.println("是否有环:" + hasCycle(head));
Node enterNode = getEnterNode(head);
System.out.println("环的入口:" + enterNode.value);
System.out.println(getCycleSize(enterNode));
}
// 环的长度
public static Integer getCycleSize(Node node) {
Node start = node;
int len = 1;
while (node.next != start) {
len++;
node = node.next;
}
return len;
}
// 如果有环的话,慢指针和快指针一定会在环上的某个点相遇,但不一定是环的入口
public static boolean hasCycle(Node head) {
Node fast = head;
Node slow = head;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) {
return true;
}
}
return false;
}
// 环的入口节点
public static Node getEnterNode(Node head) {
// 先求出快慢指针的相遇点
Node fast = head;
Node slow = head;
Node cross = null;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
if (slow == fast) {
cross = fast;
break;
}
}
// 从链表头部和相遇点开始,每次移动一个节点,他们相遇点就是环的入口
Node start = head;
while (start != null && cross != null) {
if (start == cross) {
return cross;
}
start = start.next;
cross = cross.next;
}
return null;
}
public static class Node {
Node next;
int value;
public Node(int value) {
super();
this.value = value;
}
}
}
知识兔