题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路
思考一个更简单的问题
查找链表中是否有环的方法
-
如果链表长度等于1或2直接返回否
-
设置两个节点,分别为p1=root.next、p2root.next.next
-
循环
==》 每次使p1前进一步,p2前进两步 -
若发现p1与p2相等,则返回true
-
若发现p1或p2为空,则返回false
这道题是问题a的延伸,首先要确定是否有环,若有环,找出环的入口节点
假设我们有如下一个链表:
解题过程与思路:
我们在上图中的推导中证明的是:p1、p2第一次相遇位置与环入口节点的距离,等于根节点与环入口节点的距离。
整个链表不重复节点为11个,因为有环的存在,所以不重复的路径也为11(5+6)个。相遇时p1走了6步,p2走了12步,都在6的位置,而且相遇点距离环入口节点相差5步。
所以讲p2重新指向root(节点0),并改为一次循环走一步,下次相遇p1,p2相遇的位置就是入口节点啦~
下面是通用的推导过程:
重点就是这个证明,证明出来了,解题方法就能说的通了。
证明:p1、p2第一次相遇的位置与环入口节点的距离,等于根节点与环入口节点的距离
代码
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
*/
public class Solution {
ListNode EntryNodeOfLoop(ListNode pHead){
if(pHead == null || pHead.next == null)
return null;
ListNode p1 = pHead;
ListNode p2 = pHead;
while(p2 != null && p2.next != null ){
p1 = p1.next;
p2 = p2.next.next;
if(p1 == p2){
p2 = pHead;
while(p1 != p2){
p1 = p1.next;
p2 = p2.next;
}
if(p1 == p2)
return p1;
}
}
return null;
}
}