链表 | LeetCode 142 环形链表II

68 阅读2分钟

题目描述

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

本题思路

class Solution {
public:
    ListNode* detectCycle(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast != NULL && fast->next != NULL) {
            fast = fast->next->next;
            slow = slow->next;
            if (slow == fast) {
                ListNode* index1 = head;
                ListNode* index2 = fast;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }
        }
        return NULL;
    }
};

第一理解

快慢指针判断有环,因为如果有环快指针一定会与慢指针相等(快指针相对于慢指针的前进速度其实就是一个节点。就是如果有环,再慢指针进入环中,快指针会以一个结点的速度靠近慢指针。),无环那么判断到最后,快指针自己和后一个就会为空指针。

设从头结点到环形入口节点的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。相遇时,slow指针走了x+y,fast指针走了x+y+n(y+z).慢指针一步一节点,快指针一步两节点。所以快指针所走过的路等于慢指针的两倍即 2(x+y)=x+y+n(y+z) 化简为x = n (y + z) - y 。当n为1时,从头结点出发和相遇节点同时出发都走一个节点那么会在环形入口点相遇。如果还有问题看代码随想录后面补充的数学解释.

第二理解

第一次有没有理解的地方就是在n>1怎么办?(代码随想录中的解释)

那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。

其实这种情况和n为1的时候 效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。

现在看就十分清晰。之前总以为x就只会等于z。但其实x利用公式所得,如果n==2,那么x = 2 (y + z) - y,化简得x = y +2z。index1没有走到,index2在环中绕圈,直到绕完两圈。