题目:如果一个链表中包含环,如何找出环的入口节点?例如:在如图所示的链表中,环的入口节点是节点3;
话不多上,上代码:
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null||pHead.next==null) //如果节点为空
return null;
ListNode pAhead = pHead; //定义两个节点A,B
ListNode pBhead = pHead;
while(pBhead!=null&&pBhead.next!=null){ //pBhead和pBhead.next不能唯恐
pAhead = pAhead.next; //其中A每次走一步,B走两步
pBhead = pBhead.next.next;
if(pBhead==pAhead){ //当pBhead追赶上pAhead时说明有环;
pBhead = pHead; //此时将pBhead设置成头节点方便找环入口
while(pAhead!=pBhead){
pAhead = pAhead.next; //这里注释写不清,后面见分析
pBhead = pBhead.next;
}
return pBhead;
}
}
return null;
}
}
分析:
1)如何判定链表是否有环?
定义两个指针,pAhead和pBhead。其中pBhead每次走两步,pAhead每次走一步。倘若pBhead能够追上pAhead,则说明该链表内部有环。
2)如何确定环的入口点:
当pBhead经过x步追上pAhead时,我们假设环内的节点个数时n。那么有
2x = n+x; 可以得到
n =x ; 此时说明怕pAhead走过的步骤刚好为环内节点数;
3) 先定义两个指针p1和p2指向链表的头节点。指针p1现在链表上向前移动n(环内的节点数)步,然后两个指针以同样的速度向前移动。当第二个节点指向换的入口节点时,第一个指针已经围绕着环走了一圈,又回到了入口节点。此时p1==p2;也就是代码中的pAhead = pHead;