Open In App

Minimize the number of steps required to reach the end of the array

Improve
Improve
Like Article
Like
Save
Share
Report

Given an integer array arr[] of length N consisting of positive integers, the task is to minimize the number of steps required to reach the index ‘N-1’. At a given step if we are at index ‘i’ we can go to index ‘i-arr[i]’ or ‘i+arr[i]’ given we have not visited those indexes before. Also, we cannot go outside the bounds of the array. Print -1 if there is not possible way.
Examples: 
 

Input : arr[] = {1, 1, 1}
Output : 2
The path will be 0 -> 1 -> 2.
Step 1 - 0 to 1
Step 2 - 1 to 2

Input : {2, 1}
Output : -1

This problem can be solved using dynamic programming approach.
Let’s discuss an approach that might seem correct at start. Let’s suppose we are at ith index. Can we directly say that dp[i] = 1 + min( dp[i-arr[i]], dp[i+arr[i]] ) ?
No, we cannot. The path we took to reach the index ‘i’ also matters as indexes we used before won’t be available to visit anymore.
Thus, the only approach we are left with is trying out all the possible combinations which can be really large. In this article, we will use bit-masking approach to reduce the complexity to exponential. Our mask will be an integer value with the following features. 
 

1) If, a index 'i' is visited, ith bit 
will be set 1 in the mask.
2) Else that bit will be set 0.

The required recurrence relation will be. 
 

dp[i][mask] = 1 + min(dp[i+arr[i]][mask|(1<<i)], 
dp[i-arr[i]][mask|(1<<i)])

Below is the implementation of the above approach: 

CPP




// C++ implementation of the above approach
 
#include <bits/stdc++.h>
#define maxLen 10
#define maskLen 130
using namespace std;
 
// variable to store states of dp
int dp[maxLen][maskLen];
 
// variable to check if a given state
// has been solved
bool v[maxLen][maskLen];
 
// Function to find the minimum number of steps
// required to reach the end of the array
int minSteps(int arr[], int i, int mask, int n)
{
    // base case
    if (i == n - 1)
        return 0;
 
    if (i > n - 1 || i < 0)
        return 9999999;
    if ((mask >> i) & 1)
        return 9999999;
 
    // to check if a state has
    // been solved
    if (v[i][mask])
        return dp[i][mask];
    v[i][mask] = 1;
 
    // required recurrence relation
    dp[i][mask] = 1 + min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
                          minSteps(arr, i + arr[i], (mask | (1 << i)), n));
 
    // returning the value
    return dp[i][mask];
}
 
// Driver code
int main()
{
    int arr[] = { 1, 2, 2, 2, 1, 1 };
 
    int n = sizeof(arr) / sizeof(int);
 
    int ans = minSteps(arr, 0, 0, n);
    if (ans >= 9999999)
        cout << -1;
    else
        cout << ans;
}


Java




// Java implementation of the above approach
 
class GFG
{
 
    static int maxLen = 10;
    static int maskLen = 130;
 
    // variable to store states of dp
    static int[][] dp = new int[maxLen][maskLen];
 
    // variable to check if a given state
    // has been solved
    static boolean[][] v = new boolean[maxLen][maskLen];
 
    // Function to find the minimum number of steps
    // required to reach the end of the array
    static int minSteps(int arr[], int i, int mask, int n)
    {
        // base case
        if (i == n - 1)
        {
            return 0;
        }
 
        if (i > n - 1 || i < 0)
        {
            return 9999999;
        }
        if ((mask >> i) % 2 == 1)
        {
            return 9999999;
        }
 
        // to check if a state has
        // been solved
        if (v[i][mask])
        {
            return dp[i][mask];
        }
        v[i][mask] = true;
 
        // required recurrence relation
        dp[i][mask] = 1 + Math.min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
                                minSteps(arr, i + arr[i], (mask | (1 << i)), n));
 
        // returning the value
        return dp[i][mask];
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = {1, 2, 2, 2, 1, 1};
 
        int n = arr.length;
 
        int ans = minSteps(arr, 0, 0, n);
        if (ans >= 9999999)
        {
            System.out.println(-1);
        }
        else
        {
            System.out.println(ans);
        }
    }
}
 
/* This code contributed by PrinciRaj1992 */


Python




# Python3 implementation of the above approach
maxLen = 10
maskLen = 130
 
 
# variable to store states of dp
dp = [[ 0 for i in range(maskLen)] for i in range(maxLen)]
 
# variable to check if a given state
# has been solved
v = [[False for i in range(maskLen)] for i in range(maxLen)]
 
# Function to find the minimum number of steps
# required to reach the end of the array
def minSteps(arr, i, mask, n):
 
    # base case
    if (i == n - 1):
        return 0
 
    if (i > n - 1 or i < 0):
        return 9999999
 
    if ((mask >> i) & 1):
        return 9999999
 
    # to check if a state has
    # been solved
    if (v[i][mask] == True):
        return dp[i][mask]
    v[i][mask] = True
 
    # required recurrence relation
    dp[i][mask] = 1 + min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
                        minSteps(arr, i + arr[i], (mask | (1 << i)), n))
 
    # returning the value
    return dp[i][mask]
 
 
# Driver code
 
arr=[1, 2, 2, 2, 1, 1]
 
n = len(arr)
 
ans = minSteps(arr, 0, 0, n)
 
if (ans >= 9999999):
    print(-1)
else:
    print(ans)
     
# This code is contributed by mohit kumar 29   


C#




// C# implementation of the above approach
using System;
 
class GFG
{
     
    static int maxLen = 10;
    static int maskLen = 130;
 
    // variable to store states of dp
    static int[,] dp = new int[maxLen, maskLen];
 
    // variable to check if a given state
    // has been solved
    static bool[,] v = new bool[maxLen, maskLen];
 
    // Function to find the minimum number of steps
    // required to reach the end of the array
    static int minSteps(int []arr, int i, int mask, int n)
    {
        // base case
        if (i == n - 1)
        {
            return 0;
        }
 
        if (i > n - 1 || i < 0)
        {
            return 9999999;
        }
        if ((mask >> i) % 2 == 1)
        {
            return 9999999;
        }
 
        // to check if a state has
        // been solved
        if (v[i, mask])
        {
            return dp[i, mask];
        }
        v[i, mask] = true;
 
        // required recurrence relation
        dp[i,mask] = 1 + Math.Min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
                                minSteps(arr, i + arr[i], (mask | (1 << i)), n));
 
        // returning the value
        return dp[i,mask];
    }
 
    // Driver code
    static public void Main ()
    {
        int []arr = {1, 2, 2, 2, 1, 1};
 
        int n = arr.Length;
 
        int ans = minSteps(arr, 0, 0, n);
        if (ans >= 9999999)
        {
            Console.WriteLine(-1);
        }
        else
        {
            Console.WriteLine(ans);
        }
    }
}
 
/* This code contributed by ajit. */


Javascript




<script>
 
    // Javascript implementation of
    // the above approach
     
    let maxLen = 10;
    let maskLen = 130;
   
    // variable to store states of dp
    let dp = new Array(maxLen);
    for(let i = 0; i < maxLen; i++)
    {
        dp[i] = new Array(maskLen);
    }
   
    // variable to check if a given state
    // has been solved
    let v = new Array(maxLen);
    for(let i = 0; i < maxLen; i++)
    {
        v[i] = new Array(maskLen);
    }
   
    // Function to find the minimum number of steps
    // required to reach the end of the array
    function minSteps(arr, i, mask, n)
    {
        // base case
        if (i == n - 1)
        {
            return 0;
        }
   
        if (i > n - 1 || i < 0)
        {
            return 9999999;
        }
        if ((mask >> i) % 2 == 1)
        {
            return 9999999;
        }
   
        // to check if a state has
        // been solved
        if (v[i][mask])
        {
            return dp[i][mask];
        }
        v[i][mask] = true;
   
        // required recurrence relation
        dp[i][mask] = 1 + Math.min(minSteps(arr, i - arr[i],
        (mask | (1 << i)), n), minSteps(arr, i + arr[i],
        (mask | (1 << i)), n));
   
        // returning the value
        return dp[i][mask];
    }
     
    let arr = [1, 2, 2, 2, 1, 1];
   
    let n = arr.length;
 
    let ans = minSteps(arr, 0, 0, n);
    if (ans >= 9999999)
    {
      document.write(-1);
    }
    else
    {
      document.write(ans);
    }
     
</script>


Output

3

Time Complexity: O(N*(2N))

Auxiliary Space: O(maxLen + maskLen)

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a DP to store the solution of the subproblems and initialize it with 9999999.
  • Initialize the DP with base cases
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
  • At last return answer if exists in dp[n-1]

Implementation :

C++




// C++ code for above approach
 
#include <bits/stdc++.h>
#define maxLen 10
#define maskLen 130
using namespace std;
 
// Function to find the minimum number of steps
// required to reach the end of the array
int minSteps(int arr[], int n)
{
    // DP table to store solutions to subproblems
    int dp[n];
    memset(dp, 9999999, sizeof(dp));
    dp[0] = 0;
 
    // DP table to keep track of visited states
    bool v[n][maskLen];
    memset(v, false, sizeof(v));
    v[0][0] = true;
 
    // Filling up the DP table using recurrence relation
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (v[i][j]) {
                if (i + arr[i] < n) {
                    dp[i + arr[i]] = min(dp[i + arr[i]], dp[i] + 1);
                    v[i + arr[i]][j | (1 << i)] = true;
                }
                if (i - arr[i] >= 0) {
                    dp[i - arr[i]] = min(dp[i - arr[i]], dp[i] + 1);
                    v[i - arr[i]][j | (1 << i)] = true;
                }
            }
        }
    }
 
    // Returning the final answer
    if (dp[n-1] >= 9999999)
        return -1;
    return dp[n-1];
}
 
// Driver code
int main()
{
    int arr[] = {1, 2, 2, 2, 1, 1};
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << minSteps(arr, n) << endl;
    return 0;
}


Java




import java.util.*;
 
public class Main {
 
    static final int maxLen = 10;
    static final int maskLen = 130;
 
    // Function to find the minimum number of steps
    // required to reach the end of the array
    static int minSteps(int[] arr, int n) {
 
        // DP table to store solutions to subproblems
        int[] dp = new int[n];
        Arrays.fill(dp, 9999999);
        dp[0] = 0;
 
        // DP table to keep track of visited states
        boolean[][] v = new boolean[n][maskLen];
        for (boolean[] row : v) {
            Arrays.fill(row, false);
        }
        v[0][0] = true;
 
        // Filling up the DP table using recurrence relation
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (v[i][j]) {
                    if (i + arr[i] < n) {
                        dp[i + arr[i]] = Math.min(dp[i + arr[i]], dp[i] + 1);
                        v[i + arr[i]][j | (1 << i)] = true;
                    }
                    if (i - arr[i] >= 0) {
                        dp[i - arr[i]] = Math.min(dp[i - arr[i]], dp[i] + 1);
                        v[i - arr[i]][j | (1 << i)] = true;
                    }
                }
            }
        }
 
        // Returning the final answer
        if (dp[n-1] >= 9999999) {
            return -1;
        }
        return dp[n-1];
    }
 
    // Driver code
    public static void main(String[] args) {
        int[] arr = {1, 2, 2, 2, 1, 1};
        int n = arr.length;
        System.out.println(minSteps(arr, n));
    }
}


Python3




# Python3 implementation of the above approach
 
# Function to find the minimum number of steps
# required to reach the end of the array
def min_steps(arr, n):
    # DP table to store solutions to subproblems
    dp = [9999999] * n
    dp[0] = 0
 
    # DP table to keep track of visited states
    v = [[False] * 130 for _ in range(n)]
    v[0][0] = True
 
    # Filling up the DP table using recurrence relation
    for i in range(n):
        for j in range(n):
            if v[i][j]:
                if i + arr[i] < n:
                    dp[i + arr[i]] = min(dp[i + arr[i]], dp[i] + 1)
                    v[i + arr[i]][j | (1 << i)] = True
                if i - arr[i] >= 0:
                    dp[i - arr[i]] = min(dp[i - arr[i]], dp[i] + 1)
                    v[i - arr[i]][j | (1 << i)] = True
 
    # Returning the final answer
    if dp[n - 1] >= 9999999:
        return -1
    return dp[n - 1]
 
#Driver Code
if __name__ == "__main__":
    arr = [1, 2, 2, 2, 1, 1]
    n = len(arr)
    print(min_steps(arr, n))


C#




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
class Program {
    // Maximum length of array
    static int maxLen = 10;
 
    // Maximum length of mask
    static int maskLen = 130;
 
    // Function to find the minimum number of steps
    // required to reach the end of the array
    static int minSteps(int[] arr, int n)
    {
        // DP table to store solutions to subproblems
        int[] dp = new int[n];
        Array.Fill(dp, 9999999);
        dp[0] = 0;
 
        // DP table to keep track of visited states
        bool[][] v = new bool[n][];
        for (int i = 0; i < n; i++) {
            v[i] = new bool[maskLen];
            Array.Fill(v[i], false);
        }
        v[0][0] = true;
 
        // Filling up the DP table using recurrence relation
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (v[i][j]) {
                    if (i + arr[i] < n) {
                        dp[i + arr[i]] = Math.Min(
                            dp[i + arr[i]], dp[i] + 1);
                        v[i + arr[i]][j | (1 << i)] = true;
                    }
                    if (i - arr[i] >= 0) {
                        dp[i - arr[i]] = Math.Min(
                            dp[i - arr[i]], dp[i] + 1);
                        v[i - arr[i]][j | (1 << i)] = true;
                    }
                }
            }
        }
 
        // Returning the final answer
        if (dp[n - 1] >= 9999999) {
            return -1;
        }
        return dp[n - 1];
    }
 
    // Driver code
    static void Main(string[] args)
    {
        int[] arr = { 1, 2, 2, 2, 1, 1 };
        int n = arr.Length;
        Console.WriteLine(minSteps(arr, n));
    }
}


Javascript




// Define maskLen as a constant variable
const maskLen = 130;
 
// Function to find the minimum number of steps
// required to reach the end of the array
function minSteps(arr, n) {
  // DP table to store solutions to subproblems
  const dp = new Array(n).fill(9999999);
  dp[0] = 0;
 
  // DP table to keep track of visited states
  const v = new Array(n).fill(false).map(() => new Array(maskLen).fill(false));
  v[0][0] = true;
 
  // Filling up the DP table using recurrence relation
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      if (v[i][j]) {
        if (i + arr[i] < n) {
          dp[i + arr[i]] = Math.min(dp[i + arr[i]], dp[i] + 1);
          v[i + arr[i]][j | (1 << i)] = true;
        }
        if (i - arr[i] >= 0) {
          dp[i - arr[i]] = Math.min(dp[i - arr[i]], dp[i] + 1);
          v[i - arr[i]][j | (1 << i)] = true;
        }
      }
    }
  }
 
  // Returning the final answer
  if (dp[n - 1] >= 9999999) return -1;
  return dp[n - 1];
}
 
// Driver code
const arr = [1, 2, 2, 2, 1, 1];
const n = arr.length;
console.log(minSteps(arr, n));


Output:

3

Time Complexity: O(N*N)

Auxiliary Space: O(N+N+ maskLen)



Last Updated : 20 Jul, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads