Cyclic Linked List
if (element == element1 || element == element2) {
// there is a loop!
}a -> b -> c -> d -> e -> a1. slow: a, fast1: b, fast2: c
2. slow: b, fast1: d, fast2: e
3. slow: c, fast1: a, fast2: b
4. slow: d, fast1: c, fast2: d (d == d, so there is a loop, otherwise, it would never get there)Solution
public class Demo {
public static void main(String... args) {
LinkedList<String> list = new LinkedList<>();
Node<String> a = new Node<>("a");
list.add(a);
Node<String> b = new Node<>("b");
list.add(b);
Node<String> c = new Node<>("c");
list.add(c);
Node<String> d = new Node<>("d");
list.add(d);
Node<String> e = new Node<>("e");
list.add(e);
// add a loop
e.setNext(a);
// find a loop -> two nodes are referencing the same node
// Simultaneously go through the list by ones (slow iterator) and by twos (fast iterator).
// If there is a loop the fast iterator will go around that loop twice as fast as the slow iterator.
// The fast iterator will lap the slow iterator within a single pass through the cycle.
// Detecting a loop is then just detecting that the slow iterator has been lapped by the fast iterator.
Node<String> startingNode = list.head().getNext();
Node<String> slowPointer = startingNode;
Node<String> fastPointer1;
Node<String> fastPointer2 = startingNode;
// no loop
// a -> b -> c -> d
// a | b
// b | d
// c | null -> ends the while loop
// a -> b -> c -> -> d -> e -> a
// ------------->
while (slowPointer.getNext() != null // a | b | c | d
&& (fastPointer1 = fastPointer2.getNext()) != null // b | d | a | c
&& (fastPointer2 = fastPointer1.getNext()) != null) { // c | e | b | d
System.out.println("combination: " + slowPointer.getValue() + ", " + fastPointer1.getValue() + ", " + fastPointer2.getValue());
if (slowPointer == fastPointer1 || slowPointer == fastPointer2) {
System.out.println("Loop identified!");
break;
}
slowPointer = slowPointer.getNext();
}
}
}Last updated