链表中环的入口节点
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null
确定一个链表中有环:设置两个指针,从头开始,一个走的快,一个走的慢。如果在遇到 null 之前,他们相遇,说明这个链表中有环。并且相遇的节点在环中 如何确定环的长度:从相遇节点开始,设置一个指针向后遍历,一边遍历一边计数,如果回到原来的位置,就可以得到环中节点的数目 如何确定环的入口:现在我们已经得到了环的长度,假设链表总长为 n,这个 n 值不必求,只是为了说明方便,环之前的长度为 a,环的长度为b。 设置两个节点,一个节点从头开始,此时其距离环的入口节点为 a;一个节点从距离头结点 b 长的节点开始,此时其距离尾结点的长度为 n - b - 1,尾结点之后就是环的入口节点,距离为 n - b,也就是 a。当两个节点相遇的时候,所在节点即为环的入口节点。
public class Solution {
public ListNode EntryNodeOfLoop ( ListNode pHead) {
if ( pHead == null || pHead. next == null) {
return null;
}
ListNode pMiddle = meetingNode ( pHead) ;
if ( pMiddle == null) {
return null;
}
int numOfList = count ( pMiddle) ;
if ( numOfList == 0 ) {
return null;
}
ListNode pNode1 = pHead;
ListNode pNode2 = pHead;
for ( int i= 0 ; i< numOfList; i++ ) {
pNode1 = pNode1. next;
}
while ( pNode1 != pNode2) {
pNode1 = pNode1. next;
pNode2 = pNode2. next;
}
return pNode1;
}
public int count ( ListNode pNode) {
if ( pNode == null || pNode. next == null) {
return 0 ;
}
ListNode pCount = pNode. next;
int num = 1 ;
while ( pNode != pCount) {
if ( pCount. next == null) {
return 0 ;
}
pCount = pCount. next;
num++ ;
}
return num;
}
public ListNode meetingNode ( ListNode pHead) {
if ( pHead == null || pHead. next == null) {
return null;
}
ListNode pFast = pHead;
ListNode pLow = pHead;
while ( pFast. next != null) {
pFast = pFast. next;
if ( pFast. next != null) {
pFast = pFast. next;
} else {
return null;
}
pLow = pLow. next;
if ( pFast == pLow) {
return pFast;
}
}
return null;
}
}