- 题目:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
- 思路:又学习新思路了。分3步,前两步是为了得到环所包含结点的个数n,得到n后,我们设一快一慢两个指针,快指针先走n步,然后快慢指针一起走,相遇时的结点时即为入口结点(因为环一圈也是n,而快比慢多n步,那么相遇时,刚好慢指针第一次到环入口,快指针第二次到环如何,相隔一个环n)。那么如何通过前两步得到n呢,我们也设快慢指针,快指针每次走2步,慢指针每次走1步,同时从起点出发,无限走走走,总一次会相遇(可数学证明),记录下相遇结点,然后让慢指针从相遇结点开始走,走到下一次又到相遇结点时,即为一圈,那么走了多少步,n就是多少了。编程可真有意思。
- 代码:
class Solution {
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if(pHead==null) return null;
if(pHead.next==null) return null;
ListNode pfast=pHead;//快指针
ListNode pslow=pHead;//慢指针
//直到快慢指针相遇
while(pfast!=null&&pslow!=null){
pfast=pfast.next.next;
pslow=pslow.next;
if(pfast==pslow){
break;
}
}
//记录相遇位置
ListNode mettingNode=pslow;
pslow=pslow.next;
int n=1;
//得到环内结点数
while(pslow!=mettingNode){
pslow=pslow.next;
n++;
}
//快慢结点从头开始
pslow=pHead;
pfast=pHead;
//快指针先走n步数
for(int i=0;i<n;i++) {
pfast=pfast.next;
}
//找到入口
while(pfast!=null&&pslow!=null){
if(pfast==pslow){
break;
}
pfast=pfast.next;
pslow=pslow.next;
}
return pfast;
}
}
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}