Find first node of loop in a linked list

Write a function findFirstLoopNode() that checks whether a given Linked List contains loop. If loop is present then it returns point to first node of loop. Else it returns NULL.

Example :

Input : Head of bellow linked list

Output : Pointer to node 2

We have discussed Floyd’s loop detection algorithm. Below are steps to find first node of loop.



1. If a loop is found, initialize slow pointer to head, let fast pointer be at its position.
2. Move both slow and fast pointers one node at a time.
3. The point at which they meet is the start of the loop.

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to return first node of loop.
#include <bits/stdc++.h>
using namespace std;
  
struct Node {
    int key;
    struct Node* next;
};
  
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->next = NULL;
    return temp;
}
  
// A utility function to print a linked list
void printList(Node* head)
{
    while (head != NULL) {
        cout << head->key << " ";
        head = head->next;
    }
    cout << endl;
}
  
// Function to detect and remove loop
// in a linked list that may contain loop
Node* detectAndRemoveLoop(Node* head)
{
    // If list is empty or has only one node
    // without loop
    if (head == NULL || head->next == NULL)
        return NULL;
  
    Node *slow = head, *fast = head;
  
    // Move slow and fast 1 and 2 steps
    // ahead respectively.
    slow = slow->next;
    fast = fast->next->next;
  
    // Search for loop using slow and
    // fast pointers
    while (fast && fast->next) {
        if (slow == fast)
            break;
        slow = slow->next;
        fast = fast->next->next;
    }
  
    // If loop does not exist
    if (slow != fast)
        return NULL;
  
    // If loop exists. Start slow from
    // head and fast from meeting point.
    slow = head;
    while (slow != fast) {
        slow = slow->next;
        fast = fast->next;
    }
  
    return slow;
}
  
/* Driver program to test above function*/
int main()
{
    Node* head = newNode(50);
    head->next = newNode(20);
    head->next->next = newNode(15);
    head->next->next->next = newNode(4);
    head->next->next->next->next = newNode(10);
  
    /* Create a loop for testing */
    head->next->next->next->next->next = head->next->next;
  
    Node* res = detectAndRemoveLoop(head);
    if (res == NULL)
        cout << "Loop does not exist";
    else
        cout << "Loop starting node is " << res->key;
  
    return 0;
}

chevron_right


Output:

Loop starting node is 15
Output:

Loop starting node is 15

How does this approach work?
Let slow and fast meet at some point after Floyd’s Cycle finding algorithm. Below diagram shows the situation when cycle is found.

LinkedListCycle

We can conclude below from above diagram


Distance traveled by fast pointer = 2 * (Distance traveled 
                                         by slow pointer)

(m + n*x + k) = 2*(m + n*y + k)

Note that before meeting the point shown above, fast
was moving at twice speed.

x -->  Number of complete cyclic rounds made by 
       fast pointer before they meet first time

y -->  Number of complete cyclic rounds made by 
       slow pointer before they meet first time

From above equation, we can conclude below

    m + k = (x-2y)*n

Which means m+k is a multiple of n. 

So if we start moving both pointers again at same speed such that one pointer (say slow) begins from head node of linked list and other pointer (say fast) begins from meeting point. When slow pointer reaches beginning of loop (has made m steps), fast pointer would have made also moved m steps as they are now moving same pace. Since m+k is a multiple of n and fast starts from k, they would meet at the beginning. Can they meet before also? No because slow pointer enters the cycle first time after m steps.

Method 2:
In this method, a temporary node is created. The next pointer of each node that is traversed is made to point to this temporary node. This way we are using the next pointer of a node as a flag to indicate whether the node has been traversed or not. Every node is checked to see if the next is pointing to temporary node or not. In the case of the first node of the loop, the second time we traverse it this condition will be true, hence we return that node.
The code runs in O(n) time complexity and uses constant memory space.

Below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to return first node of loop
#include <bits/stdc++.h>
using namespace std;
  
struct Node {
    int key;
    struct Node* next;
};
  
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->key = key;
    temp->next = NULL;
    return temp;
}
  
// A utility function to print a linked list
void printList(Node* head)
{
    while (head != NULL) {
        cout << head->key << " ";
        head = head->next;
    }
    cout << endl;
}
  
// Function to detect first node of loop
// in a linked list that may contain loop
Node* detectLoop(Node* head)
{
  
    // Create a temporary node
    Node* temp = new Node;
    while (head != NULL) {
  
        // This condition is for the case
        // when there is no loop
        if (head->next == NULL) {
            return NULL;
        }
  
        // Check if next is already
        // pointing to temp
        if (head->next == temp) {
            break;
        }
  
        // Store the pointer to the next node
        // in order to get to it in the next step
        Node* nex = head->next;
  
        // Make next point to temp
        head->next = temp;
  
        // Get to the next node in the list
        head = nex;
    }
  
    return head;
}
  
/* Driver program to test above function*/
int main()
{
    Node* head = newNode(50);
    head->next = newNode(20);
    head->next->next = newNode(15);
    head->next->next->next = newNode(4);
    head->next->next->next->next = newNode(10);
  
    /* Create a loop for testing */
    head->next->next->next->next->next = head->next->next;
  
    Node* res = detectLoop(head);
    if (res == NULL)
        cout << "Loop does not exist";
    else
        cout << "Loop starting node is " << res->key;
  
    return 0;
}

chevron_right


Output:

Loop starting node is 15


My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : purnasrivatsa96



Article Tags :
Practice Tags :


11


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.