Data Structure and Algorithm
Algorithms
Dynamic Programming
Min Jumps to Reach End

Minimum Jumps to Reach End

Given an array arr where each element represents the maximum number of steps that can be made forward from that index. Find the minimum number of jumps to reach the end of the array starting from index 0. If the end is not reachable, return -1.


Examples

Example 1

  • Input Array: [1, 3, 5, 8, 9, 2, 6, 7, 6, 8, 9]
  • Output: 3
  • Explanation: Jump from index 0 to 1 (1 step), then jump from index 1 to 3 (3 steps to get to 8), then jump from index 3 to the end.

Example 2

  • Input Array: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
  • Output: 9
  • Explanation: In every step, a jump of 1 is needed to reach the end.

1. Left-to-Right DP Tabulation - O(N^2)

We create a jumps array from left to right where jumps[i] indicates the minimum number of jumps needed to reach arr[i] from arr[0].

function minJumpsLeftToRight(arr) {
    const n = arr.length;
    if (n === 0 || arr[0] === 0) return -1;
 
    const jumps = new Array(n).fill(Infinity);
    jumps[0] = 0; // Base case: 0 jumps to reach index 0
 
    // Fill jumps array from left to right
    for (let i = 1; i < n; i++) {
        for (let j = 0; j < i; j++) {
            // If i is reachable from j, and it's a better jump count
            if (i <= j + arr[j] && jumps[j] !== Infinity) {
                jumps[i] = Math.min(jumps[i], jumps[j] + 1);
                break; // Optional: since we seek min jumps and move left to right, we can't find a better path here
            }
        }
    }
 
    return jumps[n - 1] === Infinity ? -1 : jumps[n - 1];
}

2. Right-to-Left DP Tabulation - O(N^2)

Alternatively, we can start from the second-to-last element, working backward to index 0, where jumps[i] represents the minimum number of jumps needed to reach the end of the array from arr[i].

function minJumpsRightToLeft(arr) {
    const n = arr.length;
    if (n === 0 || arr[0] === 0) return -1;
 
    const jumps = new Array(n).fill(Infinity);
    jumps[n - 1] = 0; // Base case: 0 jumps to reach end from end
 
    // Fill jumps array from right to left
    for (let i = n - 2; i >= 0; i--) {
        if (arr[i] === 0) {
            jumps[i] = Infinity;
        } else if (i + arr[i] >= n - 1) {
            jumps[i] = 1; // Can reach end in a single jump
        } else {
            // Find minimum jumps from reachable indexes ahead
            let min = Infinity;
            for (let j = i + 1; j < n && j <= i + arr[i]; j++) {
                if (jumps[j] < min) {
                    min = jumps[j];
                }
            }
            jumps[i] = (min !== Infinity) ? min + 1 : Infinity;
        }
    }
 
    return jumps[0] === Infinity ? -1 : jumps[0];
}

3. Optimized Greedy Approach - O(N) Time, O(1) Space

We can track the maximum reachable index, the number of steps we can still take from the current jump, and the number of jumps made.

function minJumpsGreedy(arr) {
    const n = arr.length;
    if (n <= 1) return 0;
    if (arr[0] === 0) return -1;
 
    // Stores the maximum index reachable from the current state
    let maxReach = arr[0];
 
    // Stores the number of steps we can still take
    let steps = arr[0];
 
    // Stores the number of jumps made
    let jumps = 1;
 
    // Start traversing the array
    for (let i = 1; i < n - 1; i++) {
        // Update maxReach
        maxReach = Math.max(maxReach, i + arr[i]);
 
        // Use a step to move to the current index
        steps--;
 
        // If no more steps are left
        if (steps === 0) {
            // We must have made a jump
            jumps++;
 
            // Check if a future step is possible
            if (i >= maxReach) return -1;
 
            // Re-initialize the steps to the amount of steps to reach maxReach from i
            steps = maxReach - i;
        }
    }
 
    return jumps;
}
 
// Driver code
const arr = [1, 3, 5, 8, 9, 2, 6, 7, 6, 8, 9];
console.log("Minimum jumps to reach end:", minJumpsGreedy(arr));
// Output: Minimum jumps to reach end: 3

Complexity Analysis

  • Time Complexity:
    • Dynamic Programming approaches: O(N^2)
    • Greedy/BFS approach: O(N) (single pass traversal).
  • Space Complexity:
    • Dynamic Programming: O(N) (to store the jumps array).
    • Greedy/BFS approach: O(1) auxiliary space.