题目23:链表中环的入口节点
题目描述:
一个链表中包含环,如何找出环的入口结点?例如,在图3.8的链表中,环的入口结点是结点3。
解题思路:
解决这个问题第一步是确定链表带有环。定义两个指针,一个一次一步,另一个一次两步,如果走得快的追上走得慢的,那么久包含环,如果没有追上那么就不包含;
第二步是找到环的入口,同样利用两个指针来解决,p1和p2,如果链表中环有n个节点,则指针P1先在链表上向前移动n步,然后两个指针以相同的速度向前移动,当第二个指针指向环的入口节点时,第一个指针已经绕着环走了一圈,回到入口节点。
代码实现:
package swordToOffer;
public class Num23_StartNodeOfListNode {
public static class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
/*
* 确定链表是否有环,采用快慢指针确定
* 返回值代表快慢指针相遇时的结点,返回null代表链表无环
*/
public ListNode meetingNode(ListNode head) {
if(head==null)
return null;
ListNode pSlow = head;
ListNode pFast = head;
while(pFast!=null) {
pFast = pFast.next;
pSlow = pSlow.next;
if(pFast!=null) {
pFast = pFast.next;
}
if(pSlow!=null&&pFast==pSlow) {
return pSlow;
}
}
return null;
}
public ListNode entryNodeOfLoop(ListNode head) {
ListNode meetingNode = meetingNode(head);
if(meetingNode==null)
return null;
//count node of circle
int count = 1; //initial count of node
ListNode pNode1 = meetingNode.next;
while(pNode1!=meetingNode) {
count++;
pNode1 = pNode1.next;
}
//move node1 first ,count is the count of node
pNode1 = head;
for(int i=1;i<=count;i++) {
pNode1=pNode1.next;
}
//then move node1 and ndoe2
ListNode pNode2=head;
while(pNode1!=pNode2) {
pNode1=pNode1.next;
pNode2=pNode2.next;
}
return pNode1;
}
}
考点收获
把问题拆分:找出环中任意一个节点:得到环中节点的数目;扎到环的入口节点