1306. Jump Game III
On LeetCode ->Problem¶
Given non-negative arr and starting index start, determine whether repeated jumps from index i to i - arr[i] or i + arr[i], without leaving the array, can reach any index containing 0.
Key trick¶
Treat indices as vertices in an implicit directed graph and run DFS or BFS, marking each index when discovered so cycles cannot revisit it.
Trap¶
- Forgetting the visited check can cause infinite traversal or excessive memory use.
- Marking an index only after removing it from the worklist allows duplicate insertions.
- Jumps outside the array must be ignored.
- Mutating
arrto mark visits can unexpectedly alter the caller's input.
Why is it interesting?¶
It disguises a graph reachability problem as an array problem and tests cycle handling without explicitly constructing a graph.
Python solution¶
class Solution:
def canReach(self, arr: list[int], start: int) -> bool:
n = len(arr)
stack = [start]
visited = [False] * n
visited[start] = True
while stack:
i = stack.pop()
if arr[i] == 0:
return True
jump = arr[i]
for nxt in (i - jump, i + jump):
# Mark on discovery to prevent duplicate insertions.
if 0 <= nxt < n and not visited[nxt]:
visited[nxt] = True
stack.append(nxt)
return False
Time complexity: \(O(n)\).
Space complexity: \(O(n)\).
Comment on my solution¶
The approach is correct, but these statements compare instead of assigning:
They must be assignments:
Because neighbors are never marked, cyclic paths are repeatedly enqueued and eventually exhaust memory. Mark each neighbor before enqueueing it. Your approach also mutates arr; that is valid if explicitly allowed, but a separate visited structure avoids this side effect.
# Ideas:
# - treat arr as an directed graph each element being a vertex
# - start BFS at `start` and expand left and right until
# reaching 0
# - mark in-place visited none with by setting array slot to -1
from collections import deque
# WRONG
# Memory Limit Exceeded: 3/56 testcases passed
# [1,1,1,1,2,0], 0
class Solution:
def canReach(self, arr: list[int], start: int) -> bool:
n = len(arr)
if arr[start] == 0:
return True
q = deque([(start, arr[start])]) # index, jump
arr[start] = -1
while q:
idx, jump = q.popleft()
left_idx = idx - jump
right_idx = idx + jump
if 0 <= left_idx < n:
next_jump = arr[left_idx]
if next_jump == 0:
return True
if next_jump != -1:
arr[left_idx] == -1
q.append((left_idx, next_jump))
if 0 <= right_idx < n:
next_jump = arr[right_idx]
if next_jump == 0:
return True
if next_jump != -1:
arr[right_idx] == -1
q.append((right_idx, next_jump))
return False