Given a linked list, determine if it contains a cycle. If a cycle is present, find the node where the cycle begins and return it. If there is no cycle, return nullptr.

Sample Input:

1 -> 2 -> 3 -> 4 -> 5 -> 2 (the 'next' pointer of 5 points back to 2)

Expected Output:

Node with value 2

In this example, the linked list has a cycle, as indicated by the ‘next’ pointer of node 5 pointing back to node 2. The cycle begins at node 2, so the expected output is the node with value 2.

Time and Space Complexity:


The time complexity of the algorithm should be O(n), where ‘n’ is the number of nodes in the linked list. The space complexity is O(1) as we are using a constant amount of additional memory.

Now, let’s provide the C++ solution with comments explaining the code:

#include <iostream>

// Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(nullptr) {}
};

ListNode* detectCycle(ListNode* head) {
    // Use two pointers: slow and fast
    ListNode* slow = head;
    ListNode* fast = head;

    // Initialize a flag to detect if a cycle exists
    bool hasCycle = false;

    // Traverse the linked list with two pointers
    while (fast != nullptr && fast->next != nullptr) {
        // Move slow pointer one step at a time
        slow = slow->next;

        // Move fast pointer two steps at a time
        fast = fast->next->next;

        // If there's a cycle, the two pointers will meet at some point
        if (slow == fast) {
            hasCycle = true;
            break;
        }
    }

    // If there is no cycle, return nullptr
    if (!hasCycle) {
        return nullptr;
    }

    // Reset the slow pointer to the head of the linked list
    slow = head;

    // Move both pointers at the same pace until they meet again
    while (slow != fast) {
        slow = slow->next;
        fast = fast->next;
    }

    // At this point, the slow pointer and fast pointer will meet at the start of the cycle
    return slow;
}

int main() {
    // Create the linked list for the sample input
    ListNode* node1 = new ListNode(1);
    ListNode* node2 = new ListNode(2);
    ListNode* node3 = new ListNode(3);
    ListNode* node4 = new ListNode(4);
    ListNode* node5 = new ListNode(5);

    node1->next = node2;
    node2->next = node3;
    node3->next = node4;
    node4->next = node5;
    node5->next = node2; // Point the last node back to node2, creating a cycle

    // Find the node where the cycle begins
    ListNode* cycleStart = detectCycle(node1);

    if (cycleStart != nullptr) {
        std::cout << "Node with value " << cycleStart->val << " is the start of the cycle.\n";
    } else {
        std::cout << "No cycle found in the linked list.\n";
    }

    // Don't forget to free the allocated memory
    delete node1;
    delete node2;
    delete node3;
    delete node4;
    delete node5;

    return 0;
}

The detectCycle function is an extension of the “Linked List Cycle” problem. It uses two pointers, slow and fast, to detect if a cycle exists. Once a cycle is found, it resets the slow pointer to the head of the linked list and then moves both pointers at the same pace until they meet again at the start of the cycle.

In the given example, the function will correctly find the node with value 2 as the start of the cycle and return it. The time complexity of this approach is O(n) because in the worst case, both pointers will traverse the entire linked list once. The space complexity is O(1) as we are only using two pointers regardless of the size of the input linked list.