Problem: Circular Array Loop

You are playing a game involving a circular array of non-zero integers `nums`.
Each `nums[i]` denotes the number of indices forward/backward you must move if
you are located at index `i`:

* If `nums[i]` is positive, move `nums[i]` steps forward, and
* If `nums[i]` is negative, move `nums[i]` steps backward.

Since the array is circular, you may assume that moving forward from the last
element puts you on the first element, and moving backwards from the first
element puts you on the last element.

A cycle in the array consists of a sequence of indices `seq` of length `k`
where:

* Following the movement rules above results in the repeating index sequence `seq[0] -> seq[1] -> ... -> seq[k - 1] -> seq[0] -> ...`
* Every `nums[seq[j]]` is either all positive or all negative.
* `k > 1`

Return `true` if there is a cycle in `nums`, or `false` otherwise.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def circularArrayLoop(self, nums: List[int]) -> bool:
    def advance(i: int) -> int:
      return (i + nums[i]) % len(nums)

    if len(nums) < 2:
      return False

    for i, num in enumerate(nums):
      if num == 0:
        continue

      slow = i
      fast = advance(slow)
      while num * nums[fast] > 0 and num * nums[advance(fast)] > 0:
        if slow == fast:
          if slow == advance(slow):
            break
          return True
        slow = advance(slow)
        fast = advance(advance(fast))

      slow = i
      sign = num
      while sign * nums[slow] > 0:
        next = advance(slow)
        nums[slow] = 0
        slow = next

    return False


Java solution:
class Solution {
  public boolean circularArrayLoop(int[] nums) {
    if (nums.length < 2)
      return false;

    for (int i = 0; i < nums.length; ++i) {
      if (nums[i] == 0)
        continue;
      int slow = i;
      int fast = advance(nums, slow);
      while (nums[i] * nums[fast] > 0 && nums[i] * nums[advance(nums, fast)] > 0) {
        if (slow == fast) {
          if (slow == advance(nums, slow))
            break;
          return true;
        }
        slow = advance(nums, slow);
        fast = advance(nums, advance(nums, fast));
      }

      slow = i;
      final int sign = nums[i];
      while (sign * nums[slow] > 0) {
        final int next = advance(nums, slow);
        nums[slow] = 0;
        slow = next;
      }
    }

    return false;
  }

  private int advance(int[] nums, int i) {
    final int n = nums.length;
    final int val = (i + nums[i]) % n;
    return i + nums[i] >= 0 ? val : n + val;
  }
}


C++ solution:
class Solution {
 public:
  bool circularArrayLoop(vector<int>& nums) {
    const int n = nums.size();
    if (n < 2)
      return false;

    auto advance = [&](int i) {
      const int val = (i + nums[i]) % n;
      return i + nums[i] >= 0 ? val : n + val;
    };

    for (int i = 0; i < n; ++i) {
      if (nums[i] == 0)
        continue;
      int slow = i;
      int fast = advance(slow);
      while (nums[i] * nums[fast] > 0 && nums[i] * nums[advance(fast)] > 0) {
        if (slow == fast) {
          if (slow == advance(slow))
            break;
          return true;
        }
        slow = advance(slow);
        fast = advance(advance(fast));
      }

      slow = i;
      const int sign = nums[i];
      while (sign * nums[slow] > 0) {
        const int next = advance(slow);
        nums[slow] = 0;
        slow = next;
      }
    }

    return false;
  }
};