Skip to content
Related Articles

Related Articles

Improve Article
Check if end of a sorted Array can be reached by repeated jumps of one more, one less or same number of indices as previous jump
  • Last Updated : 21 Apr, 2021

Given a sorted array arr[] of size N, the task is to check if it is possible to reach the end of the given array from arr[1] by jumping either arr[i] + k – 1, arr[i] + k, or arr[i] + k + 1 in each move, where k represents the number of indices jumped in the previous move. Consider K = 1 initially. If it is possible, then print “Yes”. Otherwise, print “No”.

Examples:

Input: arr[] = {0, 1, 3, 5, 6, 8, 12, 17}
Output: Yes
Explanation: 
Step 1: Take (k + 1 = 2) steps to move to index containing A[1] + 2 = 3
Step 2: Take (k = 2) steps to move to index containing A[2] + 2 = 5.
Step 3: Take (k + 1 = 3) steps to move to index containing A[3] + 3 = 8
Step 4: Take (k + 1 = 4) steps to move to index containing A[5] + 4 = 12
Step 4: Take (k + 1 = 5) steps to move to index containing A[6] + 5 = 17
Since the last array index contains 17, the end of the array is reached.

Input: arr[] = {0, 1, 2, 3, 4, 8, 9, 11}
Output: No

Naive Approach: The idea is to use recursion. From index i, recursively move to index having value A[i] + K – 1, A[i] + K, or A[i] + K + 1, and check whether it is possible to reach the end. If there exist any path to reach the end then print “Yes” else print “No”



Time Complexity: O(2N)
Auxiliary Space: O(1)

Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming. Create a 2D table memo[N][N] to store the memorized results. For any index (i, j), memo[i][j] denotes if it is possible to move from index i to end(N-1) and previously taken j steps. memo[i][j] = 1 denotes possible and memo[i][j] = 0 denotes not possible. Follow the steps to solve the problem:

  • Create a memoized table memo[][] of size N*N.
  • For any index (i, j) update the memo[][] table as per the following:
    • If i equals (N – 1), return 1 as the end position is reached.
    • If memo[i][j] is already calculated, then return memo[i][j].
    • Check any index having A[i] + j, A[i] + j – 1 or A[i] + j + 1 value, and recursively check is it possible to reach end.
    • Store the value in memo[i][j] and return the value.
  • If it’s possible to reach the end, print “Yes”.
  • Else, print “No”.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
#define N 8
 
// Utility function to check if it is
// possible to move from index 1 to N-1
int check(int memo[][N], int i,
          int j, int* A)
{
    // memo[i][j]: Stores if it is
    // possible to move from index i
    // to end(N-1) previously j steps
 
    // Successfully reached end index
    if (i == N - 1)
        return 1;
 
    // memo[i][j] is already calculated
    if (memo[i][j] != -1)
        return memo[i][j];
 
    // Check if there is any index
    // having value of A[i]+j-1,
    // A[i]+j or A[i]+j+1
    int flag = 0, k;
    for (k = i + 1; k < N; k++) {
 
        // If A[k] > A[i] + j + 1,
        // can't make a move further
        if (A[k] - A[i] > j + 1)
            break;
 
        // It's possible to move A[k]
        if (A[k] - A[i] >= j - 1
            && A[k] - A[i] <= j + 1)
 
            // Check is it possible to
            // move from index k
            // having previously taken
            // A[k] - A[i] steps
            flag = check(memo, k,
                         A[k] - A[i], A);
 
        // If yes then break the loop
        if (flag)
            break;
    }
 
    // Store value of flag in memo
    memo[i][j] = flag;
 
    // Return memo[i][j]
    return memo[i][j];
}
 
// Function to check if it is possible
// to move from index 1 to N-1
void checkEndReach(int A[], int K)
{
 
    // Stores the memoized state
    int memo[N][N];
 
    // Initialize all values as -1
    memset(memo, -1, sizeof(memo));
 
    // Initially, starting index = 1
    int startIndex = 1;
 
    // Function call
    if (check(memo, startIndex, K, A))
        cout << "Yes";
    else
        cout << "No";
}
 
// Driver Code
int main()
{
    int A[] = { 0, 1, 3, 5, 6,
                8, 12, 17 };
    int K = 1;
 
    // Function Call
    checkEndReach(A, K);
 
    return 0;
}

Java




// Java program for the above approach
import java.io.*;
 
class GFG{
 
static int N = 8;
 
// Utility function to check if it is
// possible to move from index 1 to N-1
static int check(int[][] memo, int i,
                 int j, int[] A)
{
     
    // memo[i][j]: Stores if it is
    // possible to move from index i
    // to end(N-1) previously j steps
 
    // Successfully reached end index
    if (i == N - 1)
        return 1;
 
    // memo[i][j] is already calculated
    if (memo[i][j] != -1)
        return memo[i][j];
 
    // Check if there is any index
    // having value of A[i]+j-1,
    // A[i]+j or A[i]+j+1
    int flag = 0, k;
     
    for(k = i + 1; k < N; k++)
    {
         
        // If A[k] > A[i] + j + 1,
        // can't make a move further
        if (A[k] - A[i] > j + 1)
            break;
 
        // It's possible to move A[k]
        if (A[k] - A[i] >= j - 1 &&
            A[k] - A[i] <= j + 1)
 
            // Check is it possible to
            // move from index k
            // having previously taken
            // A[k] - A[i] steps
            flag = check(memo, k, A[k] - A[i], A);
 
        // If yes then break the loop
        if (flag != 0)
            break;
    }
 
    // Store value of flag in memo
    memo[i][j] = flag;
 
    // Return memo[i][j]
    return memo[i][j];
}
 
// Function to check if it is possible
// to move from index 1 to N-1
static void checkEndReach(int A[], int K)
{
 
    // Stores the memoized state
    int[][] memo = new int[N][N];
 
    // Initialize all values as -1
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            memo[i][j] = -1;
        }
    }
 
    // Initially, starting index = 1
    int startIndex = 1;
 
    // Function call
    if (check(memo, startIndex, K, A) != 0)
        System.out.println("Yes");
    else
        System.out.println("No");
}
 
// Driver Code
public static void main(String[] args)
{
    int[] A = { 0, 1, 3, 5, 6, 8, 12, 17 };
    int K = 1;
 
    // Function Call
    checkEndReach(A, K);
}
}
 
// This code is contributed by akhilsaini

Python3




# Python3 program for the above approach
N = 8
 
# Utility function to check if it is
# possible to move from index 1 to N-1
def check(memo, i, j, A):
   
  # memo[i][j]: Stores if it is
  # possible to move from index i
  # to end(N-1) previously j steps
   
  # Successfully reached end index
  if (i == N - 1):
    return 1
 
  # memo[i][j] is already calculated
  if (memo[i][j] != -1):
    return memo[i][j]
 
  # Check if there is any index
  # having value of A[i]+j-1,
  # A[i]+j or A[i]+j+1
  flag = 0
   
  for k in range(i + 1, N):
     
    # If A[k] > A[i] + j + 1,
    # can't make a move further
    if (A[k] - A[i] > j + 1):
      break
 
    # It's possible to move A[k]
    if (A[k] - A[i] >= j - 1 and
        A[k] - A[i] <= j + 1):
       
      # Check is it possible to
      # move from index k
      # having previously taken
      # A[k] - A[i] steps
      flag = check(memo, k,
                   A[k] - A[i], A)
 
      # If yes then break the loop
      if (flag != 0):
        break
         
  # Store value of flag in memo
  memo[i][j] = flag
 
  # Return memo[i][j]
  return memo[i][j]
 
# Function to check if it is possible
# to move from index 1 to N-1
def checkEndReach(A, K):
   
  # Stores the memoized state
  memo = [[0] * N] * N
 
  # Initialize all values as -1
  for i in range(0, N):
    for j in range(0, N):
      memo[i][j] = -1
 
  # Initially, starting index = 1
  startIndex = 1
 
  # Function call
  if (check(memo, startIndex, K, A) != 0):
    print("Yes")
  else:
    print("No")
 
# Driver Code
if __name__  == '__main__':
   
  A = [ 0, 1, 3, 5, 6, 8, 12, 17 ]
  K = 1
 
  # Function Call
  checkEndReach(A, K)
   
# This code is contributed by akhilsaini

C#




// C# program for the above approach
using System;
 
class GFG{
 
static int N = 8;
// Utility function to check if it is
// possible to move from index 1 to N-1
static int check(int[,] memo, int i,
                 int j, int[] A)
{
     
    // memo[i][j]: Stores if it is
    // possible to move from index i
    // to end(N-1) previously j steps
 
    // Successfully reached end index
    if (i == N - 1)
        return 1;
 
    // memo[i][j] is already calculated
    if (memo[i, j] != -1)
        return memo[i, j];
 
    // Check if there is any index
    // having value of A[i]+j-1,
    // A[i]+j or A[i]+j+1
    int flag = 0, k;
    for(k = i + 1; k < N; k++)
    {
         
        // If A[k] > A[i] + j + 1,
        // can't make a move further
        if (A[k] - A[i] > j + 1)
            break;
 
        // It's possible to move A[k]
        if (A[k] - A[i] >= j - 1 &&
            A[k] - A[i] <= j + 1)
 
            // Check is it possible to
            // move from index k
            // having previously taken
            // A[k] - A[i] steps
            flag = check(memo, k, A[k] - A[i], A);
 
        // If yes then break the loop
        if (flag != 0)
            break;
    }
 
    // Store value of flag in memo
    memo[i, j] = flag;
 
    // Return memo[i][j]
    return memo[i, j];
}
 
// Function to check if it is possible
// to move from index 1 to N-1
static void checkEndReach(int[] A, int K)
{
     
    // Stores the memoized state
    int[,] memo = new int[N, N];
 
    // Initialize all values as -1
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < N; j++)
        {
            memo[i, j] = -1;
        }
    }
 
    // Initially, starting index = 1
    int startIndex = 1;
 
    // Function call
    if (check(memo, startIndex, K, A) != 0)
        Console.WriteLine("Yes");
    else
        Console.WriteLine("No");
}
 
// Driver Code
public static void Main()
{
    int[] A = { 0, 1, 3, 5, 6, 8, 12, 17 };
    int K = 1;
 
    // Function Call
    checkEndReach(A, K);
}
}
 
// This code is contributed by akhilsaini

Javascript




<script>
 
// JavaScript program for the above approach
let N = 8;
 
// Utility function to check if it is
// possible to move from index 1 to N-1
function check(memo, i, j, A)
{
     
    // memo[i][j]: Stores if it is
    // possible to move from index i
    // to end(N-1) previously j steps
  
    // Successfully reached end index
    if (i == N - 1)
        return 1;
  
    // memo[i][j] is already calculated
    if (memo[i][j] != -1)
        return memo[i][j];
  
    // Check if there is any index
    // having value of A[i]+j-1,
    // A[i]+j or A[i]+j+1
    let flag = 0, k;
      
    for(k = i + 1; k < N; k++)
    {
         
        // If A[k] > A[i] + j + 1,
        // can't make a move further
        if (A[k] - A[i] > j + 1)
            break;
  
        // It's possible to move A[k]
        if (A[k] - A[i] >= j - 1 &&
            A[k] - A[i] <= j + 1)
  
            // Check is it possible to
            // move from index k
            // having previously taken
            // A[k] - A[i] steps
            flag = check(memo, k, A[k] - A[i], A);
  
        // If yes then break the loop
        if (flag != 0)
            break;
    }
  
    // Store value of flag in memo
    memo[i][j] = flag;
  
    // Return memo[i][j]
    return memo[i][j];
}
  
// Function to check if it is possible
// to move from index 1 to N-1
function checkEndReach(A, K)
{
  
    // Stores the memoized state
    let memo = new Array(N);
     
    // Loop to create 2D array using 1D array
    for(var i = 0; i < memo.length; i++)
    {
        memo[i] = new Array(2);
    }   
  
    // Initialize all values as -1
    for(let i = 0; i < N; i++)
    {
        for(let j = 0; j < N; j++)
        {
            memo[i][j] = -1;
        }
    }
  
    // Initially, starting index = 1
    let startIndex = 1;
  
    // Function call
    if (check(memo, startIndex, K, A) != 0)
        document.write("Yes");
    else
        document.write("No");
}
 
// Driver code
let A = [ 0, 1, 3, 5, 6, 8, 12, 17 ];
let K = 1;
 
// Function Call
checkEndReach(A, K);
 
// This code is contributed by avijitmondal1998
 
</script>
Output: 
Yes

 

Time Complexity: O(N3)
Auxiliary Space: O(N2)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer DSA Live Classes




My Personal Notes arrow_drop_up
Recommended Articles
Page :