1、如何判断一个单链表是否存在闭环;
2、求闭环长度
3、求入环节点
代码实现:
package com.sort.demo;
import com.sort.demo.pojo.Node;
/**
* 关于单链表闭环问题
*/
public class NodeCycle {
/**
* 判断是否存在闭环
* <p>
* 思路:两个指针分别指向起始位置,P1每次移动一步,P2每次移动2步;当P1 == P2时则表示存在闭环
*
* @param root
* @return
*/
public static boolean isCycle(Node root) {
if (getFirstMeetNode(root) != null) {
return true;
}
return false;
}
private static Node getFirstMeetNode(Node root) {
Node p1 = root;
Node p2 = root;
while (p2 != null && p2.next != null) {
p1 = p1.next;
p2 = p2.next.next;
if (p1 == p2) {
return p1;
}
}
return null;
}
/**
* 获取闭环长度
* 首次相遇点到再次相遇,P2刚好比P1多一圈
*
* @param root
* @return
*/
public static int cycleLength(Node root) {
Node p1 = getFirstMeetNode(root);
Node p2 = p1;
int step1 = 0;
int step2 = 0;
while (p2 != null && p2.next != null) {
p1 = p1.next;
step1++;
p2 = p2.next.next;
step2 += 2;
if (p1 == p2) {
return step2 - step1;
}
}
return -1;
}
/**
* 获取入环节点
* @param root
*/
public static Node enterCycleNode(Node root) {
Node p1 = getFirstMeetNode(root);
Node p2 = root;
while (p1 != null && p2 != null) {
p1 = p1.next;
p2 = p2.next;
while (p1 == p2) {
return p1;
}
}
return null;
}
public static void main(String[] args) {
Node node1 = new Node(5);
Node node2 = new Node(3);
Node node3 = new Node(7);
Node node4 = new Node(2);
Node node5 = new Node(6);
Node node6 = new Node(8);
Node node7 = new Node(1);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node5.next = node6;
node6.next = node7;
node7.next = node4;
System.out.println("是否存在闭环:" + isCycle(node1));
System.out.println("闭环长度:" + cycleLength(node1));
System.out.println("入环节点:" + enterCycleNode(node1).data);
}
}
运行结果:
是否存在闭环:true
闭环长度:4
入环节点:2