算法-leetcode-每日一题-链表环的入口点

分析:该题本质上分解为2个题,一个是判断一个链表是否有环,另一个则寻找环的入口点。如何判断一个链表有环,相信很多人都知道:

定义两个指针fast和slow,慢指针一次走一步,快指针一次走两步。没走一次快指针都要跟慢指针比较,知道快指针等于慢指针为止,就证明有环。但是为什么这样就能判断链表有环可能很多人就不知道了。

其实这是数学归纳法:首先,由于链表是个环,所以相遇的过程可以看作是快指针从后边追赶慢指针的过程。那么做如下思考:1:快指针与慢指针之间差一步。此时继续往后走,慢指针前进一步,快指针前进两步,两者相遇。2:快指针与慢指针之间差两步。此时继续往后走,慢指针前进一步,快指针前进两步,两者之间相差一步,转化为第一种情况。

而同样如何找到如环点,解法就是:先找到fast和slow的相遇点,然后在让一个指针从链表头出发,一个指针从相遇点出发,每次走一步,当两个指针相遇就是入环点

证明:
在slow指针遍历完链表前,fast已经循环n圈(n>=1)。假设slow走了s步,fast走了2s步,设环长为r,则2s=s+nr→s=nr;设起点到入环点的距离为a,入环点到相遇点的距离为x,整个链长L,则a+x = s = nr = (n-1)r+r = (n-1)r+L-a。所以a = (n-1)r + (L – a - x),这表明链表头到环入口点等于(n-1)循环内环+相遇点到环入口点,于是在链表头与相遇点分别设一个指针,每次各走一步,两个指针必定相遇,且为入环点。

在这里插入图片描述

public static Node FindLoopPort(Node head) {
    Node slow = head, fast = head;
    while(fast != null && fast.next != null) {//这个循环是找到相遇点
        slow = slow.next; fast = fast.next.next;
        if(slow == fast) { break; }
    }
    if(fast == null || fast.next == null) { return null; }
    slow = head;//这里的slow是链头,fast是相遇点
    while(slow != fast) {
        slow = slow.next; fast = fast.next;
    }
    return slow;
}

猜你喜欢

转载自blog.csdn.net/wujingchangye/article/details/88599916