题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解:
这道题如果用O(n2)做法,可以直接根据每个节点是否能回到本节点或是末尾来判断环入口,代码也较为简洁,当然你需要从链表尾部倒着开始,否则会死循环。
这里介绍一种比较巧妙的做法,可以在O(n)时间内完成。我们根据以往的“操场追赶”经验,速度快的总是能在环里追上速度慢的,而如果不存在环,那么速度快的会直接跑到终点,而非相遇。所以我们只需要设置一个快节点,一个慢节点,每次快一步,如果有环就会相遇。那么环入口就需要计算了,我们根据数学关系可知,设起点到入口为x,相遇点距离入口y(未走段),那么显然快节点走过的路程是(x+n圈环-y),慢节点走过的路程为(x+m圈环-y),同时快=2*慢,那么就有(x+n圈环-y)=2*(x+m圈环-y),化简,x=y+k圈环,所以如果我们让一个节点从头走起,让一个在环内循环走,那么第一次相遇就会是在入口处。
建议自己画个图感受一下。
代码:
/*
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 || pHead.next.next==null){
return null;
}
ListNode slow=pHead.next;
ListNode fast=pHead.next.next;
while(slow!=fast){
if(slow==null || fast.next==null){
return null;
}
slow=slow.next;
fast=fast.next.next;
}
slow=pHead;
while(slow!=fast){
slow=slow.next;
fast=fast.next;
}
return slow;
}
}