> ## Documentation Index
> Fetch the complete documentation index at: https://leetcode-py.wisl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> leetcode-py is a Python LeetCode practice environment generator with one CLI: lcpy. It is not a service or platform.
> Each problem is a directory under leetcode/ with README.md, solution.py, test_solution.py, helpers.py, and playground.ipynb. lcpy gen creates them from JSON templates bundled with the package.
> Examples are backed by tests; copy them verbatim.

# Circular Array Loop Python Solution with Tests

> Tested Python solution for LeetCode 457 with 20 pytest cases. Generate a practice environment with lcpy.

LeetCode 457, [Medium](/catalog/medium). Topics: [Array](/catalog/topics/array), [Hash Table](/catalog/topics/hash-table), [Two Pointers](/catalog/topics/two-pointers), Floyd's Cycle Finding Algorithm. [View on LeetCode](https://leetcode.com/problems/circular-array-loop/description/).

Generate this problem as a practice environment: tested reference solution, 20 [parametrized pytest cases](/practice/testing), and a playground notebook:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
lcpy gen -n 457   # by problem number
lcpy gen -s circular_array_loop   # by problem name
```

## Problem

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 `abs(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.

### Examples

![Example 1](https://assets.leetcode.com/uploads/2022/09/01/img1.jpg)

```
Input: nums = [2,-1,1,2,2]
Output: true
```

**Explanation:** The graph shows how the indices are connected. White nodes are jumping forward, while red is jumping backward.
We can see the cycle 0 -> 2 -> 3 -> 0 -> ..., and all of its nodes are white (jumping in the same direction).

![Example 2](https://assets.leetcode.com/uploads/2022/09/01/img2.jpg)

```
Input: nums = [-1,-2,-3,-4,-5,6]
Output: false
```

**Explanation:** The graph shows how the indices are connected. White nodes are jumping forward, while red is jumping backward.
The only cycle is of size 1, so we return false.

![Example 3](https://assets.leetcode.com/uploads/2022/09/01/img3.jpg)

```
Input: nums = [1,-1,5,1,4]
Output: true
```

**Explanation:** The graph shows how the indices are connected. White nodes are jumping forward, while red is jumping backward.
We can see the cycle 0 -> 1 -> 0 -> ..., and while it is of size > 1, it has a node jumping forward and a node jumping backward, so **it is not a cycle**.
We can see the cycle 3 -> 4 -> 3 -> ..., and all of its nodes are white (jumping in the same direction).

### Constraints

* 1 \<= nums.length \<= 5000
* -1000 \<= nums\[i] \<= 1000
* nums\[i] != 0

**Follow up:** Could you solve it in O(n) time complexity and O(1) extra space complexity?

## Solution

Reference implementation from [solution.py on GitHub](https://github.com/wislertt/leetcode-py/blob/main/leetcode/circular_array_loop/solution.py), full suite in [test\_solution.py](https://github.com/wislertt/leetcode-py/blob/main/leetcode/circular_array_loop/test_solution.py):

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
class Solution:
    # Time: O(n)
    # Space: O(1)
    def circular_array_loop(self, nums: list[int]) -> bool:
        n = len(nums)

        def nxt(i: int) -> int:
            return (i + nums[i]) % n

        for start in range(n):
            if nums[start] == 0:
                continue
            forward = nums[start] > 0

            def ok(j: int, forward: bool = forward) -> bool:
                return nums[j] != 0 and (nums[j] > 0) == forward

            slow = start
            fast = nxt(slow)
            while ok(fast) and ok(nxt(fast)):
                if slow == fast:
                    if nxt(slow) != slow:
                        return True
                    break
                slow = nxt(slow)
                fast = nxt(nxt(fast))

            # The walk from `start` cannot yield a valid cycle; mark it dead.
            i = start
            for _ in range(n):
                if not ok(i):
                    break
                nums[i], i = 0, nxt(i)
        return False
```

## Complexity

| Time | Space |
| - | - |
| O(n) | O(1) |

## Tags


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.