链表中环的口节点
就是剑指offer辣道题没错
如果一个链表中包含换环,如何找出环的入口节点?
像求链表的倒数第k个节点一样,我们采用两个一前一后的指针来找位置,同样,我们采用两个指针,如果环中有4个节点,那么就让前面的节点先走4步,后走的节点一会儿肯定会和先走的节点相遇,因为是通过一个环,肯定会在入口处(也就是出口处)遇到,但是问题是:我们不知道这个节点的位置,也不知道环中节点的数目,所以我们:
1、首先判断出节点的入口地址
2、通过两个指针来找出节点的个数
public class Main {
//找到两个元素相遇的位置,如果能相遇肯定在环内
Node MeetingNode(Node head){
if(head==null){
return null;
}
Node pSlow=head.next;
if(pSlow==null){
return null;
}
Node pFast=pSlow.next;
while(pFast!=null&&pSlow!=null){
//好巧,快的元素追上了慢的元素
if(pFast==pSlow){
return pFast;
}
pFast=pFast.next;
pSlow=pSlow.next;
//我就说么,快的元素一直追,不加快脚步怎么能追上慢的元素
if(pFast!=null){
pFast=pFast.next;
}
}
return null;
}
Node EntryNodeOfLoop(Node head){
Node meetingNode=MeetingNode(head);
if(meetingNode==null){
return null;
}
//得到环中的节点的个数
int nodeNum=1;//部位的环至少有一个节点把
Node pNode =meetingNode;
while(pNode.next!=meetingNode){
pNode=pNode.next;
++nodeNum;
}
/**
* 和那个找倒数K的节点道理一毛一样
* 让两个元素相隔K个元素,环中的元素肯定一直在环里循环,直达与那个跑的指针相遇,相遇一定在环入口处,你可以画画
*/
pNode=head;
for(int i=0;i<nodeNum;i++){
pNode=pNode.next;
}
Node tNode=head;//让这个元素从头开始遍历,去环里找那个元素
while(pNode!=tNode){
pNode=pNode.next;
tNode=tNode.next;//注意,这里不用加快tnode元素的脚步,因为他两个肯定能遇上,因为pnode在循环,你可以自己画画
}
return pNode;
}
}
class Node{
int data;
Node next;
Node(int data){
this.data=data;
this.next=null;
}
}
不懂可以看注释