リンクリストでループを検出するには、リストのすべての要素を調べて表示されている要素を保存します。 現在の要素がすでに表示されている場合は、ループがあります。
サイクルの検出は、セットを使用して要素を追加したり、セット内の要素が1のOにあるかどうかをテストしたりすることで実装できます。サイクルが検出されると、前のノードを保存する 以前に見られた要素の代わりにnullを指す。 この実装は、アルゴリズムがO(n)に含まれるため、最高のパフォーマンスを発揮します。nはリスト内の要素数です。
import java.util.HashSet; import java.util.Set; public class InterviewLinkedListCycle { public static boolean testLoopON( Node head, boolean removeCycle ){ // Input Validation if( head == null ) throw new IllegalArgumentException( "Input cannot be null" ); //Processing. Set<Integer> seen = new HashSet<Integer>(); // save the head Node current = head; // Save the previous node Node previous = null; // Loop on elements while( current != null ) { // Check for the cycle if ( seen.contains( current.data ) ){ if( removeCycle ){ // Break the loop previous.next = null; } // We have found a loop return true; } seen.add( current.data ); previous = current; current = current.next; } // No Loop found return false; } public static void main(String[] argv) throws Exception { InterviewLinkedListCycle t = new InterviewLinkedListCycle(); Node head = new Node(1); Node current = head; for( int i = 2; i < 10 ; i++ ){ current.next = new Node(i); current = current.next; } long before = System.nanoTime(); boolean found = testLoopON( head, true ); long after = System.nanoTime(); System.out.println( "Loop found = " + found + " in " + (int)(after-before)/1000 + " \u00B5 seconds" ); // Create the Loop current.next = head.next; before = System.nanoTime(); found = testLoopON( head, true ); after = System.nanoTime(); System.out.println( "Loop found = " + found + " in " + (int)(after-before)/1000 + " \u00B5 seconds" ); } } class Node { Node(Integer data){ this.data = data; } Integer data; Node next; }
Loop found = false in 34 \u00B5 seconds Loop found = true in 15 \u00B5 seconds
この例では、リンクリストにループのない呼び出しとリンクリストにループがある呼び出しの2つの呼び出しを実行します。