LeetCode -- Linked List Cycle II AC Code C 语言

Given a linked list, return the node where the cycle begins. If there is no cycle, return null.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail's next pointer is connected to. Note that pos is not passed as a parameter.

Notice that you should not modify the linked list.

Example 1:

image

Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.

Example 2:

image

Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.

Example 3:

image

Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.

Constraints:

  • The number of the nodes in the list is in the range [0, 104].
  • -105 <= Node.val <= 105
  • pos is -1 or a valid index in the linked-list.

Follow up: Can you solve it using O(1) (i.e. constant) memory?

这道题是判断链表中是否有环的升级版,但是这里不仅要判断链表中是否有环,还要判断环起点的位置。

算法证明如下:

我们设在第一次相遇时快指针 pfast 所走的路程为 x,慢指针所走的路程为 y, 因为快指针的速度是慢指针的二倍,因此,x=2y.

在链表中,我们设:链表头部 head 到 环起点的位置为 a, 从环起点到第一次相遇的位置的为 b, 第一次相遇的位置到环的末尾为 c,那么环的总长度为:d = b + c;

在第一次相遇时,我们有:

x = a + c1 * d + b = 2 * y = 2*( a + c2 * d + b )

a + c1( b + c ) + b= 2 * ( a + c2 * (b + c) + b ) = 2a + 2 * c2 ( b + c ) + 2 * b

( c1 - 2 * c2 )( b + c ) = a + b

令 n = c1 - 2 * c2;

n * ( b + c ) = a + b

那么 链表头部 head 到 环起点的位置为 a = (n - 1)( b + c ) + c

当第一次相遇时,n = 1, a = c
即: 那么 链表头部 head 到 环起点的位置 与 第一次相遇的位置到环的末尾为 c 是相等的。

那么这时候将相遇的两个指针其中一个放到 head,并以相同步速前进,再次相遇点就是环的起点。

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode *runner1, *runner2 ;
    runner1 = runner2 = head;
    
    while( runner1 != NULL ){
        if( runner1->next != NULL ){
            runner1 = runner1->next->next;
        }else{
            return NULL;
        }
        runner2 = runner2->next;
        if( runner1 == runner2 ) break;
    }
    if( runner1 == NULL ) return NULL;
    runner2 = head;
 
    while(runner1 != runner2 ){
        runner1 = runner1->next;
        runner2 = runner2->next;
    }

    return runner1;
    
}

参考资料: https://blog.csdn.net/To_be_to_thought/article/details/83958314

你可能感兴趣的:(LeetCode -- Linked List Cycle II AC Code C 语言)