The problem: you get a circular array of non-zero integers. From index i you move nums[i] steps
(forward if positive, backward if negative, wrapping around). Return true if there is a cycle that
This is cycle detection, like Linked List Cycle (LeetCode 141), with two extra rules. From each start index:
slow one step and fast two steps.slow and fast meet, there is a valid cycle.To keep it O(n), once a start fails, walk its path again and set those entries to 0. Any later walk that
reaches a 0 can stop immediately, so every index is visited a constant number of times.
def circularArrayLoop(nums: list[int]) -> bool:
n = len(nums)
def nxt(i):
return (i + nums[i]) % n
for i in range(n):
if nums[i] == 0:
continue
forward = nums[i] > 0
def ok(j): # same direction, not visited, not a 1-element loop
return nums[j] != 0 and (nums[j] > 0) == forward and nxt(j) != j
slow = fast = i
while ok(fast) and ok(nxt(fast)):
slow, fast = nxt(slow), nxt(nxt(fast))
if slow == fast:
return True
j = i # mark this failed path so it is never walked again
while nums[j] != 0 and (nums[j] > 0) == forward:
k = nxt(j)
nums[j] = 0
j = k
return False
Python’s % always returns a non-negative result, so backward moves wrap correctly. In Java or C++ use
((i + nums[i]) % n + n) % n.
| Input | Answer | Why |
|---|---|---|
[2,-1,1,2,2] |
true |
0 -> 2 -> 3 -> 0, all forward |
[-1,2] |
false |
1 -> 1 is a one-element loop |
[-2,1,-1,-2,-2] |
false |
The only loop mixes directions |
[1,-1,5,1,4] |
true |
3 -> 4 -> 3, all forward |
[-1,-1,-1] |
true |
Every element points back one step |
Worked live in an SDE Skills daily coding session (6,000+ views).
SDE Skills is a volunteer-run 501(c)(3) nonprofit with free daily LeetCode practice on Zoom. See the schedule, the free DSA practice sheet and LeetCode 564: Find the Closest Palindrome.