题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路解析
这个方法不是自己的,但是确实解法很巧妙因此就以此方法作为博客内容了。
原方法地址:https://blog.nowcoder.net/n/deaa284f105e48f49f38b5d7cb809cd7?f=comment
思路描述:
假设链表结构如下:
- 首先判断是否是环。设置两个指针,fasth和slwo。fast一次走两步,slow一次走一步。fast肯定会比slow更早的进入环中,且经过多次循环,最终如果和slow相遇了(假设相遇在P点),说明fast一直在转圈,存在环。
在这个过程中slow走过的距离是a+b
,fast走过的距离是:a+nb+(n-1)c
。(这里的n倍b和n-1倍c的原因是,由于最后在P点相遇了,因此fast说走的路程少1个c)
因此速度关系式如下:2(a+b) = a+nb+(n-1)c 可知,由于要满足等式关系,n = 2。而得到a = c。- 然后在进行环入口的判断。
设置slow2从pHead开始进入,而slow此时正从相遇的q点出发。由于a = c,当slow2于slow相遇的地方,就是环入口点。
代码
/*
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 fast = pHead;
ListNode slow = pHead;
while(fast!=null||fast.next!=null){
//由于如果存在环,就会一直循环下去,如果不存在环,就会在满足要求后跳出循环,返回一个null
fast = fast.next.next;//快指针一次走两步
slow = slow.next;//慢指针一次走一步
if(fast==slow){
//当快慢指针相遇
ListNode slow2 = pHead;
while(slow2!=slow){
slow2 = slow2.next;//slow2指针从phead出进入一次走一步当与slow相遇即为环入口
slow = slow.next;
}
return slow2;
}
}
return null;
}
}