题目
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
代码
-
该题目和第12题“链表中倒数第k个节点”方法类似
-
需要使用快慢两个指针,然后根据指针的移动找到环的入口节点
-
本题目需要解决三个问题
- 1、怎么判断链表是否有环?
- 2、判断有环后,怎么知道环的入口几点在哪?
- 3、环的节点数目是多少?
-
答:
-
问题1、使用两个快慢的指针,分别为p1和p2,然后块指针每次移动两个节点,慢指针移动一个节点。如果块指针追上慢指针,那么就判断链表中有环,但是找到的节点并不一定是环的入口节点,否则没有环。MeetingNode函数就是解决这个问题的
-
问题2、如何判断环的节点数目?首先根据问题1,记录链表中判断出来的一个节点,我们可以从这个节点出发,重新的走一遍这个环,同时记录出现的节点个数,回到起点节点时,那么次数就是环中节点的个数sum
-
问题3、根据环中节点的个数,然后将快指针首先移动sum下,慢指针从头链表开始,每次快慢指针都走一个节点,如果出现快慢节点的重合,那么记录下重合的节点,这个节点就是链表中环的入口节点。
-
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead){
ListNode meetingNode = MeetingNode(pHead);
if(meetingNode==null)
return null;
int sumLoopNode = 1;
ListNode loopNode = meetingNode;
while(loopNode.next!=meetingNode){
loopNode = loopNode.next;
sumLoopNode++;
}
ListNode pHead1 = pHead;
for(int i=0;i<sumLoopNode;i++){
pHead1 = pHead1.next;
}
ListNode pHead2 =pHead;
while(pHead1!=pHead2){
pHead1 = pHead1.next;
pHead2 = pHead2.next;
}
return pHead1;
}
public ListNode MeetingNode(ListNode pHead){
if(pHead==null)
return null;
ListNode slowNode = pHead.next;
if(slowNode==null)
return null;
ListNode fastNode = slowNode.next;
while(slowNode!=null && fastNode!=null){
if(slowNode==fastNode)
return slowNode;
slowNode=slowNode.next;
for(int i=0;i<2;i++)
fastNode = fastNode.next;
}
return null;
}
}