Minimize the number of steps required to reach the end of the array
Last Updated :
20 Jul, 2023
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
#include <bits/stdc++.h>
#define maxLen 10
#define maskLen 130
using namespace std;
int dp[maxLen][maskLen];
bool v[maxLen][maskLen];
int minSteps( int arr[], int i, int mask, int n)
{
if (i == n - 1)
return 0;
if (i > n - 1 || i < 0)
return 9999999;
if ((mask >> i) & 1)
return 9999999;
if (v[i][mask])
return dp[i][mask];
v[i][mask] = 1;
dp[i][mask] = 1 + min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
minSteps(arr, i + arr[i], (mask | (1 << i)), n));
return dp[i][mask];
}
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
class GFG
{
static int maxLen = 10 ;
static int maskLen = 130 ;
static int [][] dp = new int [maxLen][maskLen];
static boolean [][] v = new boolean [maxLen][maskLen];
static int minSteps( int arr[], int i, int mask, int n)
{
if (i == n - 1 )
{
return 0 ;
}
if (i > n - 1 || i < 0 )
{
return 9999999 ;
}
if ((mask >> i) % 2 == 1 )
{
return 9999999 ;
}
if (v[i][mask])
{
return dp[i][mask];
}
v[i][mask] = true ;
dp[i][mask] = 1 + Math.min(minSteps(arr, i - arr[i], (mask | ( 1 << i)), n),
minSteps(arr, i + arr[i], (mask | ( 1 << i)), n));
return dp[i][mask];
}
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);
}
}
}
|
Python
maxLen = 10
maskLen = 130
dp = [[ 0 for i in range (maskLen)] for i in range (maxLen)]
v = [[ False for i in range (maskLen)] for i in range (maxLen)]
def minSteps(arr, i, mask, n):
if (i = = n - 1 ):
return 0
if (i > n - 1 or i < 0 ):
return 9999999
if ((mask >> i) & 1 ):
return 9999999
if (v[i][mask] = = True ):
return dp[i][mask]
v[i][mask] = True
dp[i][mask] = 1 + min (minSteps(arr, i - arr[i], (mask | ( 1 << i)), n),
minSteps(arr, i + arr[i], (mask | ( 1 << i)), n))
return dp[i][mask]
arr = [ 1 , 2 , 2 , 2 , 1 , 1 ]
n = len (arr)
ans = minSteps(arr, 0 , 0 , n)
if (ans > = 9999999 ):
print ( - 1 )
else :
print (ans)
|
C#
using System;
class GFG
{
static int maxLen = 10;
static int maskLen = 130;
static int [,] dp = new int [maxLen, maskLen];
static bool [,] v = new bool [maxLen, maskLen];
static int minSteps( int []arr, int i, int mask, int n)
{
if (i == n - 1)
{
return 0;
}
if (i > n - 1 || i < 0)
{
return 9999999;
}
if ((mask >> i) % 2 == 1)
{
return 9999999;
}
if (v[i, mask])
{
return dp[i, mask];
}
v[i, mask] = true ;
dp[i,mask] = 1 + Math.Min(minSteps(arr, i - arr[i], (mask | (1 << i)), n),
minSteps(arr, i + arr[i], (mask | (1 << i)), n));
return dp[i,mask];
}
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);
}
}
}
|
Javascript
<script>
let maxLen = 10;
let maskLen = 130;
let dp = new Array(maxLen);
for (let i = 0; i < maxLen; i++)
{
dp[i] = new Array(maskLen);
}
let v = new Array(maxLen);
for (let i = 0; i < maxLen; i++)
{
v[i] = new Array(maskLen);
}
function minSteps(arr, i, mask, n)
{
if (i == n - 1)
{
return 0;
}
if (i > n - 1 || i < 0)
{
return 9999999;
}
if ((mask >> i) % 2 == 1)
{
return 9999999;
}
if (v[i][mask])
{
return dp[i][mask];
}
v[i][mask] = true ;
dp[i][mask] = 1 + Math.min(minSteps(arr, i - arr[i],
(mask | (1 << i)), n), minSteps(arr, i + arr[i],
(mask | (1 << i)), n));
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>
|
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++
#include <bits/stdc++.h>
#define maxLen 10
#define maskLen 130
using namespace std;
int minSteps( int arr[], int n)
{
int dp[n];
memset (dp, 9999999, sizeof (dp));
dp[0] = 0;
bool v[n][maskLen];
memset (v, false , sizeof (v));
v[0][0] = true ;
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 ;
}
}
}
}
if (dp[n-1] >= 9999999)
return -1;
return dp[n-1];
}
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 ;
static int minSteps( int [] arr, int n) {
int [] dp = new int [n];
Arrays.fill(dp, 9999999 );
dp[ 0 ] = 0 ;
boolean [][] v = new boolean [n][maskLen];
for ( boolean [] row : v) {
Arrays.fill(row, false );
}
v[ 0 ][ 0 ] = true ;
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 ;
}
}
}
}
if (dp[n- 1 ] >= 9999999 ) {
return - 1 ;
}
return dp[n- 1 ];
}
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
def min_steps(arr, n):
dp = [ 9999999 ] * n
dp[ 0 ] = 0
v = [[ False ] * 130 for _ in range (n)]
v[ 0 ][ 0 ] = True
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
if dp[n - 1 ] > = 9999999 :
return - 1
return dp[n - 1 ]
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 {
static int maxLen = 10;
static int maskLen = 130;
static int minSteps( int [] arr, int n)
{
int [] dp = new int [n];
Array.Fill(dp, 9999999);
dp[0] = 0;
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 ;
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 ;
}
}
}
}
if (dp[n - 1] >= 9999999) {
return -1;
}
return dp[n - 1];
}
static void Main( string [] args)
{
int [] arr = { 1, 2, 2, 2, 1, 1 };
int n = arr.Length;
Console.WriteLine(minSteps(arr, n));
}
}
|
Javascript
const maskLen = 130;
function minSteps(arr, n) {
const dp = new Array(n).fill(9999999);
dp[0] = 0;
const v = new Array(n).fill( false ).map(() => new Array(maskLen).fill( false ));
v[0][0] = true ;
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 ;
}
}
}
}
if (dp[n - 1] >= 9999999) return -1;
return dp[n - 1];
}
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)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...