题目描述
一个链表中包含环,请找出该链表的环的入口结点。
分析
1,找一个环中的节点
2,通过环中的节点,通过遍历计算环中的节点个数
3,如果链表中环 有n个结点,指针P1在链表上向前移动n步,然后两个指针以相同的速度向前移动。当第二个指针指向环的入口结点时,第一个指针已经围绕着环走了一圈又回到了入口结点,此时两个节点恰好在入口处相遇,即入口节点。
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;
}
int loopSum = sumLoopNode(pHead);
ListNode p1=pHead;
ListNode p2=pHead;
for (int i = 0; i < loopSum; i++) {
p1=p1.next;
}
// 通过分析,当两个节点恰好相遇时,此时就是入口节点
while(p1!=p2){
p1=p1.next;
p2=p2.next;
}
return p1;
}
// 计算环中的节点数目
private int sumLoopNode(ListNode pHead) {
// TODO Auto-generated method stub
ListNode meetNode = getMeetNode(pHead);
ListNode tempNode = meetNode.next;
int sum = 1;
while (meetNode != tempNode) {
tempNode = tempNode.next;
sum++;
}
return sum;
}
// 找到在环中的相遇节点,便于计算环中的节点数目
private ListNode getMeetNode(ListNode pHead) {
// TODO Auto-generated method stub
if (pHead == null) {
return null;
}
ListNode slow = pHead;
ListNode fast = pHead.next;
while (slow != fast) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}