Open In App

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
Improve
Improve
Like Article
Like
Save
Share
Report

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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads