You are given a list of positive numbers. In this list, each integer denotes the maximum number of jumps that you are able to make from that integer’s index to the forward direction. You need to determine the minimum number of jumps that you can make starting from the initial 0th index so that you can reach the end of the list. Please note that if an element is 0, you will not be able to make any further moves from that position.
Sample Test Cases:
Input: array[]={1, 3 ,5 ,8 ,9 ,3 ,4 ,5 ,6}
Output: 3 [ 1->3-> 8/9->6]
Explanation : Starting from the 1st element, we can jump from the 1st element to the 2nd element because only 1 jump is allowed. Now, from the 2nd element, i.e., 3, these are the choices of the number of jumps - 1, 2, 3. If we choose 2 or 3 jumps, then elements 8 and 9 can be reached from where we can easily reach the end of the array. So, the total number of jumps is 3.
Input: array[]={1,1,1}
Output: 3
Explanation . All jumps have the same value, and at every position, a jump is needed, so the final jump is 3.
Method 1: (Naive Approach)
The Naive Approach is using a simple recursive approach to recursively call all the elements that can be possible to reach from the first element in the given array. So the minimum number of jumps to reach the end from the first element can be given as:
MinimumJumps(starting position,ending position)=Minimum(minimumJumps(J,end), Where J represents all the possible jumps from the starting position.
Java:
//Importing libraries
import java.util.*;
import java.io.*;
class MinJumps {
//Function to return Maximum number of jumps to reach the end
static int MinimumJumps(int array[], int start, int end)
{
//Handling the base cases checking whether the starting
//Position equal to ending position
if (end== start)
return 0;
//Return Maximum Value if position of particular index is zero
if (array[start] == 0)
return Integer.MAX_VALUE;
int min = Integer.MAX_VALUE;
// Traverse all the points from starting position recursively
// Get the minimum value possible value
for (int i = start + 1; i <= end && i <= start + array[start];++i) {
// Recursively call next possible position from ith position
int jumps_total = MinimumJumps(array, i, end);
// Calculating the minimum jumps
if (jumps_total != Integer.MAX_VALUE && jumps_total + 1 <min)
min = jumps_total + 1;
}
// Return the minimum jumps to reach the end
return min;
}
// Driver code of the program to Find the minimum possible jump
public static void main(String args[])
{
// Array containing number of jumps for particular position
int array[] = {1,2,5,2,4,7,8,9};
// Length of the array
int length_array = array.length;
System.out.println("Total number of jumps to reach the end position " + MinimumJumps(array, 0, length_array - 1));
}
}
|
Output
C++
#include <bits/stdc++.h>
using namespace std;
//Function to return the total number of jumps to reach the end position
int MinimumJumps(int jumps_atpostion[], int n)
{
// Handling the Base Case if the size of the
// array is 1 Total number of jumps will be equal to zero
if (n == 1)
return 0;
//Transverse all the possible position recursively from particular position index
//Initialize the minimum jumps
int total_min_jumps = INT_MAX;
for (int i = n - 2; i >= 0; --i) {
if (i + jumps_atpostion[i] >= n - 1) {
int min_jumpsatparticularposition = MinimumJumps(jumps_atpostion, i + 1);
if (min_jumpsatparticularposition!= INT_MAX)
total_min_jumps = min(total_min_jumps, min_jumpsatparticularposition + 1);
}
}
// Returning the total number of jumps possible to reach the end position
return total_min_jumps;
}
// Driver Code of the program to Find the total number of jumps to reach //the end
int main()
{
int jumps_atpostion[] = {1,2,1,4,5,2,2,1};
// Length of the array
int length = sizeof(jumps_atpostion) / sizeof(jumps_atpostion[0]);
cout << "Total number of jumps required to reach the end is : "<< MinimumJumps(jumps_atpostion, length)<<endl;
return 0;
}
|
Output:
Python:
#Function to Find the minimum possible jumps to reach the end
def MinimumJumps(array, starting, ending):
# Handling Base Case if the starting index is equal to the ending index
if (starting == ending):
return 0
# Checking if the jump at a particular position is zero if zero return maximum value
if (array[starting] == 0):
return float('inf')
total_min_jumps = float('inf')
for starting_index in range(starting + 1, ending + 1):
if (starting_index < starting + array[starting] + 1):
jump_at_particularPosition = MinimumJumps(array, starting_index, ending)
# Updating the total_min_jumps
if (jump_at_particularPosition != float('inf') and jump_at_particularPosition + 1 < total_min_jumps):
total_min_jumps = jump_at_particularPosition + 1
return total_min_jumps
# Driver program to Find the minimum Jumps to reach the end position
array = [1, 3, 6, 3, 1, 3, 6, 8, 9, 5]
# Length of the array
n = len(array)
print('Total number of jumps to reach the end position', MinimumJumps(array, 0, n-1))
|
Output:
Complexity :
- Time Complexity : O(n^n). There are maximum n possible moves from the particular element. So, the upper bound for the complexity of this program is O(n^n).
- Auxiliary Space: The Auxiliary Space Complexity of this program is O(1) if we ignore the stack space. Otherwise, the Space Complexity of this program will be O(n) because of the stack space in every recursive call in each step.
Note : Above approach is a time-consuming approach and not an optimized approach because there are many cases when one subproblem is called one or more times. Hence there will be overlapping subproblems. For example, Minimumjump(3, 6) will be called two times as array[3] can be called from array[1] and array[2]. There are two methods (tabular and memoization) to overcome this problem, both of which use, Dynamic programming.
Method 2 - (Tabular):
Dynamic Programming is the optimization of recursion. In the above, we encounter many overlapping problems. We can optimize this using Dynamic Programming. The idea is simply to store the answer to the subproblems so that we do not recompute a particular subproblem whenever we encounter any function call. This simple approach reduces the time complexity of the program from exponential to polynomial.
Approach:
- We make jumps [] array in which i’th index of the jumps[i’th] indicates the minimum jump to reach jumps[i] from the jump[0] position.
- Fill the jumps[0] to 0.
- The outer loop runs from 1 to n-1, and the inner loop from 0 to n-1.
- Initially, set jumps[i] to INT MAX. If i is less than j + array[j], then set jumps[i] to minimum of jumps[i] and jumps[j] + 1.
- Finally, return the jumps[n-1] that is the total minimum jump.
JAVA:
import java.util.*;
import java.io.*;
class Main {
private static int TotalNumberofJumps(int[] jumps_array, int length)
{
//Creating jumps array to store the minimum jumps at particular position
int jumps_at_postion[] = new int[length];
// result
int i, j;
//Handling the base case if the jump at particular position is zero or not
if (length == 0 || jumps_array[0] == 0)
return Integer.MAX_VALUE;
//Initialize the minimum jump at position 0 is zero
jumps_at_postion[0] = 0;
//Find the minimum number of jumps to reach arr[i] from arr[0]
for (i = 1; i < length; ++i) {
jumps_at_postion[i] = Integer.MAX_VALUE;
for (j = 0; j < i; ++j) {
if (i <= j + jumps_array[j]
&& jumps_at_postion[j]
!= Integer.MAX_VALUE) {
// Storing the min jumps to reach at position i
jumps_at_postion[i] = Math.min(jumps_at_postion[i], jumps_at_postion[j] + 1);
break;
}
}
}
//Returning the Total number of jumps to reach the end position
return jumps_at_postion[length-1];
}
// Driver program to Find the total number of Jumps to reach the end
public static void main(String[] args)
{
// Array containing the maximum jumps possible at particular position
int Jump_array[] = {1, 3, 6, 3, 1, 3, 6, 8, 9, 5};
System.out.println("Total Number of jumps to reach the end position : "
+ TotalNumberofJumps(Jump_array, Jump_array.length));
}
}
|
Output:
Python:
#Function to Find Total number of jumps to reach the end position
def Minimum_jumps(jump_array, n):
jumps_at_position = [0 for i in range(n)]
#Handling the base Cases if the jump at particular position is zero or not
if (n == 0) or (jump_array[0] == 0):
return float('inf')
#Initialise the jumps array at position 0 to 0
jumps_at_position[0] = 0
#Find the minimum number of jumps need to reach jumps[i] from jumps[0]
for i in range(1, n):
jumps_at_position[i] = float('inf')
for j in range(i):
if (i <= j + jump_array[j]) and (jumps_at_position[j] != float('inf')):
#Storing the Minimum jump to reach at position i
jumps_at_position[i] = min(jumps_at_position[i], jumps_at_position[j] + 1)
break
return jumps_at_position[n-1]
# Driver Program to Find the total number of jumps to reach the end position
jump_array = [1, 3, 6, 3, 1, 3, 6, 8, 9, 5]
size = len(jump_array)
print('Total Number of jumps to reach the end position', Minimum_jumps(jump_array,size))
|
Output:
C++
//Importing libraries
#include <bits/stdc++.h>
using namespace std;
int min(int a, int b)
{ return (a < b) ? a : b; }
//Function to return the minimum number of jumps
int MinimumJumps(int jump_array[], int length)
{
//Creating jumps array to store the minimum jumps at particular position
int* jumps_at_position = new int[length];
int i, j;
//Creating jumps array to store the minimum jumps at particular position
if (length == 0 || jump_array[0] == 0)
return INT_MAX;
//Initialize the minimum jump at position 0 is zero
jumps_at_position [0] = 0;
// Finding the minimum jumps to reach jumps[i] from jumps[0]
for (i = 1; i < length; ++i) {
jumps_at_position [i] = INT_MAX;
for (j = 0; j < i; ++j) {
if (i <= j + jump_array[j] && jumps_at_position [j] != INT_MAX) {
// Storing the min jumps to reach at position i
jumps_at_position [i] = min(jumps_at_position [i], jumps_at_position [j] + 1);
break;
}
}
}
//Returning the Total number of jumps to reach the end position
return jumps_at_position[length - 1];
}
// Driver code of the program to find the minimum possible jumps
int main()
{
// Array containing the maximum jumps possible at particular position
int jump_array[] = {1, 3, 6, 3, 1, 3, 6, 8, 9, 5};
// length of the array
int length = sizeof(jump_array) / sizeof(int);
cout << "Total Number of jumps to reach the end position "
<< MinimumJumps(jump_array, length)<<endl;
return 0;
}
|
Output:
Complexity:
- Time complexity : O(n^2). Because a nested traversal of the array is needed.
- Auxiliary Space :O(n). To store the DP array, we need O(n) space.
Method 3: (Memoization)
The memoization Approach is the extension of the recursion approach with some variation in recursion. The main disadvantage of the recursion is there are many overlapping causes like Minimumjumps(3, 9) that will be called two times as array[3] can be reached from array[1] and array[2]. So, we generally store the answer to subproblems in an array and return the answer of that subproblem that whenever we encounter a particular subproblem in any other function call. This process speeds up the program and increases the efficiency of the code.
JAVA:
import java.util.*;
import java.io.*;
class Main
{
//Function to Find total number of jumps need to reach the end position
public static int Minimum_jumps(int[] jumps_array, int starting_index, int length, int[] dp)
{
//Base Case if starting index reach to the ending index
if (starting_index == length - 1) {
return 0;
}
//Handling the base Cases if the jump at particular position is zero or not
if (starting_index >= length || jumps_array[starting_index] == 0) {
return Integer.MAX_VALUE;
}
//Checking whether the particular recursive call answer exists in the array or not
if (dp[starting_index] != 0) {
return dp[starting_index];
}
int minjumps = Integer.MAX_VALUE;
for (int j = starting_index + 1; j <= starting_index + jumps_array[starting_index]; ++j)
{
//Recursively call to the next possible jump from ith index
int min_jumps_particularindex = Minimum_jumps(jumps_array, j, length, dp);
if ( min_jumps_particularindex != Integer.MAX_VALUE) {
minjumps = Math.min(minjumps, min_jumps_particularindex+ 1);
}
}
// Storing the recursive call answer if not present in the dp array
return (dp[starting_index] = minjumps);
}
//Driver code to Find the total number of jumps to reach the end position
public static void main(String[] args)
{
int[] jumps_at_particular_position = { 1, 3, 6, 1, 0, 9 };
//Array to store the recursive call answer i.e memoization
int[] dp = new int[jumps_at_particular_position.length];
System.out.println("Total number of jumps to reach the end position is " +Minimum_jumps(jumps_at_particular_position ,0, jumps_at_particular_position.length, dp));
}
}
|
Output:
C++:
#include <bits/stdc++.h>
using namespace std;
//Function to Find the Minimum of two numbers
int minjumps(int a, int b) { return (a < b) ? a: b; }
//Function to find total number of jumps to reach the end position
int MinimumJumps(int jump_array[], int starting_index, int ending, int Min_jumps_value_atposition[])
{
if (starting_index == ending - 1) {
return 0;
}
//Handling the base Cases if the jump at particular position is zero or not
if (starting_index >= ending || jump_array[starting_index] == 0) {
return INT_MAX;
}
//Checking whether the particular recursive call answer exits in the array or not
if ( Min_jumps_value_atposition[starting_index] != 0){
return Min_jumps_value_atposition[starting_index];
}
int Minjumpsatposition = INT_MAX;
for (int j = starting_index + 1; j <= starting_index + jump_array[starting_index]; j++)
{
int min_jumps_particularindex = MinimumJumps(jump_array, j, ending, Min_jumps_value_atposition);
if (min_jumps_particularindex != INT_MAX) {
Minjumpsatposition = minjumps( Minjumpsatposition, min_jumps_particularindex + 1);
}
}
// if the subproblem is seen for the first time
return (Min_jumps_value_atposition[starting_index] = Minjumpsatposition);
}
int main( )
{
int array[] = { 1, 3, 6, 1, 0, 9};
int length = sizeof(array) / sizeof(array[0]);
// Creating an array to store the total jump at particular position
int jumps[length];
memset(jumps, 0, length * sizeof(int));
printf("Total Number of jumps to reach the ending position %d\n" ,MinimumJumps(array, 0, length, jumps));
return 0;
}
|
Output
Python:
import sys
#Function to Find Total_number_of_jumps to reach the end position
def findMinJumps(A, starting_index, length, dp):
# Checking base check if starting_index is equal to the ending index or not
if starting_index == length - 1:
return 0
#Checking whether the jump at particular index is zero or not
if starting_index >= length or A[starting_index] == 0:
return sys.maxsize
# if the answer of particular recursive call exists in the array or not
if dp[starting_index]:
return dp[starting_index]
# Find the minimum jump to reach the end position and store in the min_jumps
min_jumps = sys.maxsize
for j in range(starting_index + 1, starting_index + A[starting_index] + 1):
cost = findMinJumps(A, j, length, dp)
if cost != sys.maxsize:
min_jumps = min(min_jumps, cost + 1)
# if the recursive call occurs first time store the answer
dp[starting_index] = min_jumps
return dp[starting_index]
jump_array = [1, 3, 6, 1, 0, 9]
#Create an array to store the recursive call answers
dp = [0] * len(jump_array)
print("The minimum jumps required to reach the destination are",
findMinJumps(jump_array, 0, len(jump_array), dp))
Output:
Complexity:
- Time complexity : O(n^2). Because a nested traversal of the array is needed.
- Auxiliary Space : O(n). To store the DP array, we need O(n) space.
Conclusion
Finding minimum jumps required to reach the destination is one of the most famous problems of Dynamic Programming. There are many variations that exist for this problem as well. In this article, we have discussed three approaches to solve this problem. The Naive Approach, i.e., a simple recursion, the other is the optimized approach, i.e., Memoization, and the third one is the Dynamic Programming approach which is the most optimized approach.
The optimized approach overcomes the overlapping recursive calls which are present in the Naive Approaches. That’s why we generally prefer DP and Memoization instead of plain recursion when we have large constraints. We certainly hope that this article will help you understand this problem in greater detail.
Happy Learning!
People are also reading: