First approach that you may think may something look like:
- Traverse through each node till end , tracking visited node using visited flag.
- If you find node that is already visited, then there is a loop in LinkedList and if you reach till end while traversing then there is no loop in LinkedList
Efficient approach:
Efficient approach for this problem would be Floyd’s cycle detection
algorithm,so steps for this algo would be:
- Use two pointer fastPtr and slowPtr and initialize both to head of linkedlist
- Move fastPtr by two nodes and slowPtr by one node in each iteration.
- If fastPtr and slowPtr meet at some iteration , then there is a loop in linkedlist.
- If fastPtr reaches to the end of linkedlist without meeting slow pointer then there is no loop in linkedlist (i.e fastPtr->next or fastPtr->next->next become null.
- Java code for this algo will be
public boolean ifLoopExists() {
Node fastPtr = head;
Node slowPtr = head;
while (fastPtr != null && fastPtr.next != null) {
fastPtr = fastPtr.next.next;
slowPtr = slowPtr.next;
if (slowPtr == fastPtr)
return true;
}
return false;
}
public static void breakLoop(ListNode head) {
ListNode loopStart = detectLoop(head);
if (loopStart == null) {
System.out.println("No loop detected.");
return;
}
// Find the node just before the start of the loop
ListNode current = loopStart;
while (current.next != loopStart) {
current = current.next;
}
// Break the loop
current.next = null;
System.out.println("Loop broken at node with value: " +
loopStart.value);
}
Let's create a linked list without a loop :
Let's create a java program called “LinkedList.java”
public class LinkedList{ private Node head; private static class Node { private int value; private Node next; Node(int value) { this.value = value; } } public void addToTheLast(Node node) { if (head == null) { head = node; } else { Node temp = head; while (temp.next != null) temp = temp.next; temp.next = node; } } public void printList() { Node temp = head; while (temp != null) { System.out.format("%d ", temp.value); temp = temp.next; } System.out.println(); } public boolean ifLoopExists() { Node fastPtr = head; Node slowPtr = head; while (fastPtr != null && fastPtr.next != null) { fastPtr = fastPtr.next.next; slowPtr = slowPtr.next; if (slowPtr == fastPtr) return true; } return false; } public static void main(String[] args) { LinkedList list = new LinkedList(); // Creating a linked list list.addToTheLast(new Node(5)); list.addToTheLast(new Node(6)); list.addToTheLast(new Node(7)); list.addToTheLast(new Node(1)); list.addToTheLast(new Node(2)); list.printList(); // Test if loop existed or not System.out.println("Loop existed-->" + list.ifLoopExists()); } }
Run above program, you will get following output:
5 6 7 1 2 Loop existed-->false
Let's create a loop in LinkedList
Now we will connect last node to the nodewith value 7 and it will create loop in linked list, so change above main method to this:
public static void main(String[] args) { LinkedList list = new LinkedList(); // Creating a linked list Node loopNode=new Node(7); list.addToTheLast(new Node(5)); list.addToTheLast(new Node(6)); list.addToTheLast(loopNode); list.addToTheLast(new Node(1)); list.addToTheLast(new Node(2)); list.printList(); // creating a loop list.addToTheLast(loopNode); // Test if loop existed or not System.out.println("Loop existed-->" + list.ifLoopExists()); }
Logically our linkedlist with loop can be represented as :
so this is how you can detect a loop in linkedlist.
5 6 7 1 2 Loop existed-->true