Loop Node5 Next pointer is point to Node3 in Singly Linked List 1 ---- 2 ---- 3 ---- 4 ---- 5 |_____________|
- Hashmap
- Floyd’s cycle detection Algorithm
- Fast and Slow pointer
Hash Map Method
- Start Traversing Linked List
- Repeat 3, 4 untill LinkedList’s end
- Search current node’s address in HashMap, if its not there :
Push current node’s address to Hash
else If current node’s address is found in HashMap :
LinkedList contains loop, - Come out of loop
Floyd’s Cycle Algorithm : This method is also dependent on Floyd’s Cycle detection algorithm.
1) Detect Loop using Floyd’s Cycle detection algo and get the pointer to a loop node.
2) Count the number of nodes in loop. Let the count be k.
3) Fix one pointer to the head and another to kth node from head.
4) Move both pointers at the same pace, they will meet at loop starting node.
5) Get pointer to the last node of loop and make next of it as NULL.
Logic of Algorithm :
Say Two runner are running in circular field, One runner say RunnerA runs with 10KMPH ‘s speed and one say RunnerB with 15KMPH (faster than first RunnerA), in circular path after some N rounds RunnerB will sure overtake (cross) RunnerA (means they will meet).
Same logic we are using to find loop with fast pointer and slow pointer, if they meet then they are in circular path.
W’ll keep faster Pointer to move Two steps and slow as One step.
as faster point is double as fast as slow pointer, When they meet, they will be equally far head and count of node in loop.
So Follow steps after we find loop.
- Count the number of nodes in loop. Let the count be k.
- Fix one pointer to the head and another to kth node from head.
- Move both pointers at the same pace, they will meet at loop starting node.
- Get pointer to the last node of loop and make next of it as NULL.
Code is given below
struct node { int data; struct node* next; }; int detectLoop(struct node *list) { struct node *slow_p = list, *fast_p = list; while (slow_p && fast_p && fast_p->next) { slow_p = slow_p->next; fast_p = fast_p->next->next; if (slow_p == fast_p) { return 1; //to indicate loop is there } return 0; //to indeciate that ther is no loop } } void removeLoop(struct node *loop_node, struct node *head) { struct node *ptr1 = loop_node; struct node *ptr2 = loop_node; unsigned int k = 1, i; while (ptr1->next != ptr2) { ptr1 = ptr1->next; k++; } ptr1 = head; ptr2 = head; for (i = 0; i < k; i++) ptr2 = ptr2->next; while (ptr2 != ptr1) { ptr1 = ptr1->next; ptr2 = ptr2->next; } ptr2 = ptr2->next; while (ptr2->next != ptr1) ptr2 = ptr2->next; ptr2->next = NULL; }
Method 2)
As we need to count the nodes in loop, it gives more cycles or iterations in given problem, We can think of solution where we don’t need to use K (number of nodes in Loop).
void detectAndRemoveLoop(Node *head) { Node *slow = head; Node *fast = head->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 exists */ if (slow == fast) { slow = head; while (slow != fast->next) { slow = slow->next; fast = fast->next; } /* since fast->next is the looping point */ /* remove loop */ fast->next = NULL; } }