-
判断链表是否有环,可以用快慢指针来实现
快指针一次走两步,满指针一次走一步
如果快指针为空或者其next节点为空,则表示链表没有环
如果快慢指针相遇了,则表示链表有环 -
在有环情况下,我们来找到其入环节点
解析:
-
计算环的长度
快慢指针第一次相遇后,快指针一次一步,慢指针不动,每走一步,计数一次,直到两者再次相遇,即为环的长度
public class ISCycle {
private static class Node{
int data;
Node next;
public Node(int data){
this.data=data;
}
}
/**
* 判断单链表是否有环
* @param head
* @return
*/
public static boolean isCycle(Node head){
Node A=head;
Node B=head;
while (A!=null&&A.next!=null){
A=A.next.next;
B=B.next;
if(A==B){
return true;
}
}
return false;
}
/**
* 计算单链表环的长度
* @param head
* @return
*/
public static int cycleLength(Node head){
Node A=head;
Node B=head;
boolean flag=false; //为true时证明有环,开始计数
int cycleLength=0;
while (A!=null&&A.next!=null){
A=A.next.next;
B=B.next;
if(A==B){
flag=true;
break;
}
}
if(flag==true){
A=A.next;
cycleLength++; //有环的话,最小长度也是1
while (A!=B){
cycleLength++;
A=A.next;
}
}
return cycleLength;
}
/**
* 求单链表环的入环节点
* @param head
* @return
*/
public static Node getCycleNode(Node head){
Node A=head;
Node B=head;
boolean hasCycle=false; //有无环的标志
Node cycleNode=null; //入环节点
while (A.next!=null&&A!=null){
A=A.next.next;
B=B.next;
if(A==B){
hasCycle=true;
break;
}
}
if(hasCycle==true){
B=head;
cycleNode=B; //头节点就是入环节点的情况
while (A!=B){
A=A.next;
B=B.next;
if(A==B){
cycleNode=B;
break;
}
}
return cycleNode;
}
return cycleNode;
}
public static void main(String[] args) {
Node node1=new Node(5);
Node node2=new Node(3);
Node node3=new Node(8);
Node node4=new Node(5);
Node node5=new Node(6);
Node node6=new Node(9);
node1.next=node2;
node2.next=node3;
node3.next=node4;
node4.next=node5;
node5.next=node6;
node6.next=node2;
System.out.println(isCycle(node1));
System.out.println(cycleLength(node1));
System.out.println(getCycleNode(node1).data);
}
}