Detect a Cycle in a Linked List

Problem

Build a linked list from the array. If k is not -1, the last node links back to the node at index k, which creates a cycle. If k is -1, the last node links to nothing. Print true if the list has a cycle, else false. Do not use extra memory that grows with n.

Constraints

  • 1 <= n <= 10^5
  • -1 <= k < n

Examples

Input

4
3 2 0 -4
1

Output

true

Solutions

Best approachTime O(n)Space O(1)

Floyd's algorithm: a fast runner and a slow runner. On a straight path the fast runner reaches the end. On a circular track the fast runner laps the slow one, so they meet. It needs only two pointers.

Same code works in Java810172125Basic features only, so nothing changes between versions.
/*
 * Problem : Detect a cycle.
 * Input   : n, the values, and k.
 * Output  : true or false.
 * Approach: Fast and slow pointers.
 * Time    : O(n)
 * Space   : O(1)
 * Java    : 8 or newer.
 */
import java.util.Scanner;

public class Main {
        // Step 1: A node holds one value and a link to the next node. The last node links to null.
        static class Node {
            int value;
            Node next;

            Node(int value) {
                this.value = value;
            }
        }

    // This method solves the task. It receives the input and returns the answer.
    static boolean solve(int[] a, int k) {
        // Step 2: Build the nodes and link them one after another.
        Node[] nodes = new Node[a.length];
        for (int i = 0; i < a.length; i++) {
            nodes[i] = new Node(a[i]);
            if (i > 0) {
                nodes[i - 1].next = nodes[i];
            }
        }

        // Step 3: If k is not -1, link the last node back to the node at index k.
        if (k >= 0) {
            nodes[a.length - 1].next = nodes[k];
        }

        // Step 4: Two pointers. slow moves 1 step and fast moves 2 steps. In a cycle, fast catches slow.
        Node slow = nodes[0];
        Node fast = nodes[0];
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {
                return true;
            }
        }

        // Step 5: fast reached the end of the list, so there is no cycle.
        return false;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int size = scanner.nextInt();
        int[] a = new int[size];
        for (int i = 0; i < size; i++) {
            a[i] = scanner.nextInt();
        }
        int k = scanner.nextInt();
        System.out.println(solve(a, k));
    }
}
Hints (2)
  1. What happens if fast reaches null?
  2. Why must they meet inside a cycle?