Jump Game VII

Medium
Watch on YouTube ↗

Solution

// ===================================================
// Solution 1: DFS + Memoization (TLE on large inputs)
// Time: O(n * max), Space: O(n)
// ===================================================
class Solution {
    HashMap<Integer, List<Integer>> hmap;
    int n;
    HashSet<Integer> visited;

    public boolean canReach(String s, int min, int max) {
        n = s.length();
        visited = new HashSet<>();
        hmap = new HashMap<>();

        // Precompute adjacency list: for each '0' index, store reachable '0' indices within [i+min, i+max]
        for (int i = 0; i < n; i++) {
            if (s.charAt(i) != '0') continue;

            hmap.put(i, new ArrayList<>());
            for (int j = i + min; j <= Math.min(i + max, n - 1); j++) {
                if (s.charAt(j) == '0')
                    hmap.get(i).add(j);
            }
        }

        return dfs(0);
    }

    boolean dfs(int ind) {
        if (ind == n - 1) return true;
        if (visited.contains(ind)) return false;

        visited.add(ind);

        for (int i = 0; i < hmap.get(ind).size(); i++) {
            int next = hmap.get(ind).get(i);
            if (!visited.contains(next)) {
                if (dfs(next)) return true;
            }
        }

        return false;
    }
}


// ===================================================
// Solution 2: Difference Array (Optimal)
// Time: O(n), Space: O(n)
// ===================================================
class Solution {
    public boolean canReach(String s, int min, int max) {
        int n = s.length();

        // Early exit: last index must be '0' to be reachable
        if (s.charAt(n - 1) == '1') return false;

        // Difference array to track how many valid positions can reach index i
        int[] arr = new int[n];
        int count = 0;

        for (int i = 0; i < n; i++) {
            // Apply difference array increment at this index
            count += arr[i];

            // Index i is a valid jump source if it's '0' and reachable (or is the start)
            if (i == 0 || (s.charAt(i) == '0' && count > 0)) {
                // Mark the jump range [i+min, i+max] as reachable using difference array
                if (i + min < n)     arr[i + min] += 1;
                if (i + max + 1 < n) arr[i + max + 1] -= 1;
            }
        }

        // count > 0 means at least one valid path reached the last index
        return count > 0;
    }
}