Statement

In a single-player jump game, the player starts at one end of a series of squares, with the goal of reaching the last square.

At each turn, the player can take up to ss steps towards the last square, where ss is the value of the current square.

For example, if the value of the current square is 33, the player can take either 33 steps, or 22 steps, or 11 step in the direction of the last square. The player cannot move in the opposite direction, that is, away from the last square.

You have been tasked with writing a function to validate whether a player can win a given game or not.

You’ve been provided with the nums integer array, representing the series of squares. The player starts at the first index and, following the rules of the game, tries to reach the last index.

If the player can reach the last index, your function returns TRUE; otherwise, it returns FALSE.

Constraints:

  • 11 \leq nums.length 103\leq 10^3
  • 00 \leq nums[i] 103\leq 10^3

Solution

You may have already brainstormed some approaches and have an idea of how to solve this problem. Let’s explore some of these approaches and figure out which one to follow based on considerations such as time complexity and implementation constraints.

Naive approach

The naive approach is to attempt all possible jump patterns to traverse from the initial position to the final position. The process begins at the starting position and involves jumping to every reachable index. This process is repeated until the last index is reached. In case we are unable to proceed further, a backtrack is performed to explore alternative paths. This method, although inefficient, ensures that all potential paths are explored to reach the final position. However, the time complexity of the backtracking approach will be exponential.

Optimized approach using the greedy pattern

Alternatively, an optimized approach to solve this problem is using the greedy technique by traversing our array backward. We check the elements one by one from the last element of our array. We keep track of the elements that can reach the ending point directly and verify if there are any possible paths to these indexes. We’re “greedy” because we always pick the nearest preceding element that provides a path to the ending point. We can afford to be “greedy”, since there is no danger of overshooting the target. The value at each index specifies the longest jump we can make and doesn’t restrict us from making a smaller jump if that suits us better.