【LeetCode】LeetCode刷题(5)【链表】【环形链表II】(C语言)

13

环形链表I

LeetCode刷题(3)【链表】【环形链表】&扩展_半生瓜のblog-CSDN博客


环形链表II

142. 环形链表 II - 力扣(LeetCode) (leetcode-cn.com)

这个题写起来不难,但是证明有点麻烦。

在这里插入图片描述

在这里插入图片描述


针对这个入口点怎么求,有人给出了一个结论。

结论:一个指针从meet点开始走,一个指针从链表的开始点走,它们会在入口点相遇。(看下面的过程的时候,先别想这个结论,否则会越来越乱的,就先当不知道。)


在这里插入图片描述

fast走的路程是slow走的路程的2倍。

slow走的路程:slow进环了以后,在一圈之内,fast一定会追上slow。因为slow走了一圈,fast都走两圈了。

slow进环之前,fast有可能在环里面转了N圈,如果入环之前的长度越长,环很小,N越大, 如果入环前的长度越短,环很大,N就是1,fast只转了1圈。

fast走的路程: L + C*N + X

slow走的路程:L + X

fast = 2*slow

L + C*N + X = 2 (L + X)

化简一下得:

C* N - X = L

再化简一下得: ( N - 1 )* C + C - X = L

C - X就是meet点到入口点的距离。

再看这个结论。

结论:一个指针从meet点开始走,一个指针从链表的开始点走,它们会在入口点相遇。

理解一下,就是一个指针从meet点出发,转转转了N-1圈,在走了一个C-X到达入口点,发生相遇。

代码实现:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast && fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
        //找到相遇点
        if(fast == slow)
        {
            //相等即为相遇点
            struct ListNode* meet =  slow;
            //一个指针从meet走,一个指针从head走,他们会在入口点相遇
            while(head != meet)
            {
                head = head->next;
                meet = meet->next;
            }
            return meet;
        }
    }
    return NULL;
}