剑指offer 链表中环的入口结点

£可爱£侵袭症+ 提交于 2020-01-19 05:09:07

题目

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

由定理得知:一个慢指针(每次走一步),一个快指针(每次走两步),如果该链表有环的情况下则慢指针和快指针会最终在环中相遇。
该定理可以通过数学归纳法证明:
慢指针和快指针之间相差的步数为1的时候,两个指针相差一步,如 该图为1和2两个节点
此时继续往后走,慢指针前进一步,快指针前进两步,两者相遇。
慢指针和快指针之间相差的步数为2的时候,两个指针相差两步,在这里插入图片描述此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差一步,转化为第一种情况

慢指针和快指针之间相差的步数n步时,两个指针相差n步,继续往后走,慢指针前进一步,快指针前进两步,两者之间相差N-1步。因此返回慢指针和快指针之间相差的步数为n-1的情况。
以此类推最终慢指针会和快指针相遇。

在这里插入图片描述
假设两指针在5节点相遇
设1节点到4节点距离为x,4到5为y,5到4为z。
慢指针行走距离为s,快指针为f,由题意2×s=f。
s=x-1+n(z+y)+y, f=x-2+N(z+y)+y。已知当fast指针比slow指针走多一圈时相遇,所以N=n+1;
n为slow在环里走的圈数,N为fast在环里走的圈数。所以综上所有条件得出x=z;
所以令p指针和slow指针再走x距离,便是环的入口。

public class Solution {

    public ListNode EntryNodeOfLoop(ListNode head)
    {
        if(head==null||head.next==null) return null;
        ListNode slow=head.next;
        ListNode fast=head.next.next;
        ListNode p=head;
        while(slow!=fast){
            slow=slow.next;
            fast=fast.next.next;
        }
        while(p!=slow){
            p=p.next;
            slow=slow.next;
        }
        return p;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!