📌  相关文章
📜  检查是否可以通过重复跳转与前一跳转一样多、少或相同数量的索引来到达已排序数组的末尾

📅  最后修改于: 2021-09-22 10:23:55             🧑  作者: Mango

给定一个大小为N的排序数组arr[] ,任务是通过跳转arr[i] + k – 1 , arr[i] +来检查是否有可能从arr[1] 到达给定数组的末尾k,arr[i] + k + 1在每一步,其中k代表在上一步中跳跃的索引数。最初考虑K = 1 。如果可能,则打印“是” 。否则,打印“否”

例子:

朴素的方法:这个想法是使用递归。从索引i递归移动到值为A[i] + K – 1、A[i] + KA[i] + K + 1 的索引并检查是否有可能到达终点。如果存在任何到达终点的路径,则打印“是”,否则打印“否”

时间复杂度: O(2 N )
辅助空间: O(1)

高效的方法:为了优化上述方法,思想是使用动态规划。创建一个二维表memo[N][N]来存储记忆的结果。对于任何索引(i, j)memo[i][j]表示是否可以从索引i移动到结尾(N-1)和之前采取的j步。 memo[i][j] = 1表示可能, memo[i][j] = 0表示不可能。请按照以下步骤解决问题:

  • 创建一个大小为N*N的记忆表memo[][]
  • 对于任何索引(i, j)更新memo[][]表,如下所示:
    • 如果i等于(N – 1) ,则在到达结束位置时返回 1。
    • 如果备忘录[i] [j]已经计算出,然后返回备忘录[i] [j]。
    • 检查具有A[i] + j、A[i] + j – 1A[i] + j + 1值的任何索引,并递归检查是否有可能到达终点。
    • 将值存储在memo[i][j] 中并返回值。
  • 如果可以到达终点,则打印“Yes”
  • 否则,打印“否”

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
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


输出:
Yes

时间复杂度: O(N 3 )
辅助空间: O(N 2 )

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程