Given an array of non-negative integers arr
, you are initially positioned at start
index of the array. When you are at index i
, you can jump to i + arr[i]
or i - arr[i]
, check if you can reach any index with value 0.
Notice that you can not jump outside of the array at any time.
Example 1:
Input: arr = [4,2,3,0,3,1,2], start = 5 Output: true Explanation: All possible ways to reach at index 3 with value 0 are: index 5 -> index 4 -> index 1 -> index 3 index 5 -> index 6 -> index 4 -> index 1 -> index 3
Example 2:
Input: arr = [4,2,3,0,3,1,2], start = 0 Output: true Explanation: One possible way to reach at index 3 with value 0 is: index 0 -> index 4 -> index 1 -> index 3
Example 3:
Input: arr = [3,0,2,1,2], start = 2 Output: false Explanation: There is no way to reach at index 1 with value 0.
Constraints:
1 <= arr.length <= 5 * 104
0 <= arr[i] < arr.length
0 <= start < arr.length
This problem asks whether we can reach an index with a value of 0 starting from a given index in an array. The movement is constrained: from index i
, we can jump to i + arr[i]
or i - arr[i]
, provided these indices are within the array bounds.
The most efficient approach is Breadth-First Search (BFS). BFS explores the search space level by level, guaranteeing that we find the shortest path (if one exists) to a target (in this case, an index with value 0).
Algorithm:
Initialization:
q
and enqueue the start
index.visited
array (or modify the input array arr
in-place) to keep track of visited indices. This prevents cycles and redundant explorations.BFS Iteration:
i
from the queue.arr[i] == 0
, we've reached our target, so return true
.i
as visited (e.g., set arr[i] = -1
, or visited[i] = true
).next1 = i + arr[i]
and next2 = i - arr[i]
.next1
and next2
are within the array bounds (0 <= next <= arr.length -1
) and have not been visited. If they are valid and unvisited, enqueue them into the queue.No Path Found:
false
.Time and Space Complexity:
visited
array (or the space used for modifying arr
in-place).Code Examples (with detailed comments):
Python:
from collections import deque
def canReach(arr, start):
q = deque([start]) # Queue for BFS
visited = [False] * len(arr) # Array to track visited indices
while q:
i = q.popleft()
if arr[i] == 0: # Target found
return True
if visited[i]: # Already visited this index
continue
visited[i] = True # Mark as visited
next1 = i + arr[i]
next2 = i - arr[i]
if 0 <= next1 < len(arr) and not visited[next1]:
q.append(next1)
if 0 <= next2 < len(arr) and not visited[next2]:
q.append(next2)
return False # No path to index with value 0
Java:
import java.util.ArrayDeque;
import java.util.Deque;
class Solution {
public boolean canReach(int[] arr, int start) {
Deque<Integer> q = new ArrayDeque<>();
q.offer(start);
boolean[] visited = new boolean[arr.length];
while (!q.isEmpty()) {
int i = q.poll();
if (arr[i] == 0) return true;
if (visited[i]) continue;
visited[i] = true;
int next1 = i + arr[i];
int next2 = i - arr[i];
if (next1 >= 0 && next1 < arr.length && !visited[next1]) q.offer(next1);
if (next2 >= 0 && next2 < arr.length && !visited[next2]) q.offer(next2);
}
return false;
}
}
The other languages (C++, Go, TypeScript) would follow a very similar structure, using their respective queue implementations and array/list handling. The core algorithm remains the same.