已经知道一条链表的头结点,求一个链表是否带环路,以及该链表的长度。
解题思路:遇到这种问题我们可以这么解决,我们想一下以前学数学的时候有也做过这种需求的题目,当A以x的速度沿着这条路跑,B以2x的速度沿着这条路跑,问这条路是否是存在环路的,并且求这条路的长度,我们很容易会想到当A如果能与B在开始后某一时刻相遇,说明这条路是存在环路的,如果A和B永远不会相遇说明这条路不是存在环路的。同理我们可以用俩个快慢指针quick,slow都从头结点出发,slow以一个节点的速度遍历这条链表 ,quick以两个节点的速度遍历这条链表,如果存在环路,那么quick,slow 肯定会在环路上相遇,如果不存在环路,那么quick,slow是不可能相遇的。
我们可以画图分析一下:
我们看一下代码是如何实现的:
public class LinkList {
public static void main(String[] args) {
Node head=new Node(0);
Node current=head;
Node temp = null;
//构造环路链表
for(int i=1;i<11;i++){
Node node=new Node(i);
current.addNext(node);
current=node;
if(i==4){
temp=node;
}
}
current.next=temp;
if(isCirList(head)){
System.out.println("该链表存在环路");
}
System.out.println("链表长度为:"+getLength(head));
}
public static boolean isCirList(Node head){
Node quick=head;
Node slow=head;
boolean flog=false;
while(true){
quick=quick.next.next;
slow=slow.next;
if(quick==slow&&quick!=head){
flog= true;
break;
}
}
return flog;
}
public static int getLength(Node head){
Node quick=head;
Node slow=head;
//确定环内相遇点
while(true){
quick=quick.next.next;
slow=slow.next;
//System.out.println("slow"+slow.data);
//System.out.println("quick"+quick.data);
if(quick==slow&&quick!=head){
break;
}
}
//求环的长度
quick=quick.next;
int cir_len=1;
while(quick!=slow){
quick=quick.next;
cir_len++;
}
System.out.println("环长为:"+cir_len);
//求柄的长度
int bin_len=0;
quick=head;
while(quick!=slow){
quick=quick.next;
slow=slow.next;
bin_len++;
}
System.out.println("柄长为:"+bin_len);
return bin_len+cir_len;
}
}
class Node{
int data;
Node next;
Node(int data){
this.data=data;
}
public void addNext(Node node){
node.next=this.next;
this.next=node;
}
}