<p>Given an array of non-negative integers <code>arr</code>, you are initially positioned at <code>start</code>&nbsp;index of the array. When you are at index <code>i</code>, you can jump&nbsp;to <code>i + arr[i]</code> or <code>i - arr[i]</code>, check if you can reach&nbsp;<strong>any</strong> index with value 0.</p>

<p>Notice that you can not jump outside of the array at any time.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> arr = [4,2,3,0,3,1,2], start = 5
<strong>Output:</strong> true
<strong>Explanation:</strong> 
All possible ways to reach at index 3 with value 0 are: 
index 5 -&gt; index 4 -&gt; index 1 -&gt; index 3 
index 5 -&gt; index 6 -&gt; index 4 -&gt; index 1 -&gt; index 3 
</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> arr = [4,2,3,0,3,1,2], start = 0
<strong>Output:</strong> true 
<strong>Explanation: 
</strong>One possible way to reach at index 3 with value 0 is: 
index 0 -&gt; index 4 -&gt; index 1 -&gt; index 3
</pre>

<p><strong class="example">Example 3:</strong></p>

<pre>
<strong>Input:</strong> arr = [3,0,2,1,2], start = 2
<strong>Output:</strong> false
<strong>Explanation: </strong>There is no way to reach at index 1 with value 0.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= arr.length &lt;= 5 * 10<sup>4</sup></code></li>
	<li><code>0 &lt;= arr[i] &lt;&nbsp;arr.length</code></li>
	<li><code>0 &lt;= start &lt; arr.length</code></li>
</ul>

#include <vector>
#include <unordered_set>
#include <algorithm>

class Solution {
public:
    bool solve(const std::vector<int> &arr, const std::unordered_set<int> &target, int start, std::unordered_set<int> &visited) {
        // Check if the current index is out of bounds
        if (start < 0 || start >= arr.size()) {
            return false;
        }
        
        // Check if the index is already visited
        if (visited.find(start) != visited.end()) {
            return false;
        }
        
        // Mark the current index as visited
        visited.insert(start);
        
        // Check if the current index is a target
        if (target.find(start) != target.end()) {
            return true;
        }
        
        // Recursive calls for left and right shifts
        bool reAns = false;
        reAns = reAns || solve(arr, target, start - arr[start], visited);
        reAns = reAns || solve(arr, target, start + arr[start], visited);
        
        return reAns;
    }

    bool canReach(const std::vector<int>& arr, int start) {
        std::unordered_set<int> target;
        std::unordered_set<int> visited;
        
        // Collect all indices with value 0 in the target set
        for (int i = 0; i < arr.size(); ++i) {
            if (arr[i] == 0) {
                target.insert(i);
            }
        }
        
        // Start the recursive search
        return solve(arr, target, start, visited);
    }
};

52050