Skip to content

Coding patternsBlind 75

Jump Game

Track the farthest index you can reach; if you ever stand past it, you are stuck. Solved two ways, marking reachable cells in O(n²) and a greedy reach in O(n), with a step-through, code in five languages and the Big O worked out from the code.

You are given an array nums of numbers (call its length n). You start on index 0. From index i you may jump forward by any distance from 1 up to nums[i]. Return true if you can reach the last index, and false if not.

Example 1

Input: nums = [2, 3, 1, 0, 2, 0, 1]

Output: true

One way: jump 1 to index 1, jump 3 to index 4, jump 2 to index 6.

nums
20311203240516
one path
0 → 1 → 4 → 6

Example 2

Input: nums = [3, 1, 1, 0, 4]

Output: false

Every path lands on index 3, which holds 0. Nothing gets past it.

Example 3

Input: nums = [0]

Output: true

You already stand on the last index.

  • 1 ≤ n ≤ 10,000
  • 0 ≤ nums[i] ≤ 100,000
Is nums[i] the exact jump or the most?
The most. Any jump from 1 up to nums[i] is allowed.
Can we jump backward?
No. Jumps only go forward.
Do we need the path or the number of jumps?
No, only whether the last index can be reached.
Is it a problem to jump past the end?
No. A jump that could go further than the last index still reaches it, because a shorter jump is allowed.

Because every shorter jump is allowed, the reachable indexes are always one solid block from 0 up to some farthest point. So we never need to track which paths exist, only how far the block goes. One number, updated greedily as we walk, holds all of it. That is the greedy pattern.

Trying every path with plain recursion is exponential. The marking table below is that same idea, with each index handled once.

Greedy reach O(n)

Keep one number, reach: the farthest index we know we can land on. Walk the indexes from left to right.

  • If i is past reach, nothing can land on i. We are stuck, so return false.
  • Otherwise we can stand on i, so we can reach i + nums[i]. Grow reach if that is farther.

If the walk gets through every index, the last one was reachable.

Why it is correct: every index from 0 to reach can be reached, because shorter jumps are allowed. So the reachable indexes form one block, and reach is its end.

nums
20311203240516
reach
0
  1. reach = 0
  2. for i in range(len(nums)):
  3. if i > reach:
  4. return False
  5. reach = max(reach, i + nums[i])
  6. return True

reach is the farthest index we can land on so far. Every index up to reach is reachable, because jumps can be shorter than the maximum.

1 / 9
Solution.javasolution.pySolution.cssolution.gosolution.ts
class Solution {
// Greedy reach: track the farthest index we can land on. If i ever passes
// it, we are stuck. One pass, so O(n) time and O(1) memory.
public boolean canJump(int[] nums) {
int reach = 0;
for (int i = 0; i < nums.length; i++) {
// Nothing can land on i, and every later index is even farther.
if (i > reach) return false;
// Shorter jumps are allowed, so everything up to reach is reachable.
reach = Math.max(reach, i + nums[i]);
}
return true;
}
}
Time O(n)Space O(1)Here is how we get these from the code, in four steps.
  1. 1 Find the work that repeats

    Each run of the loop does one comparison and one max. That is 1 step. There is one loop.

    1. reach = 0
    2. for i in range(len(nums)):
    3. if i > reach:
    4. return False
    5. reach = max(reach, i + nums[i])
    6. return True
  2. 2 Count the runs on Example 1

    Example 1 has 7 numbers. The loop looks at each index once, and reach never falls behind i.

    7 runs.

    i0123456
    reach after2444667
  3. 3 Write the count for any n

    The loop runs once per index, or stops early when it gets stuck:

    at most n runs

    Check it with Example 1: 7 numbers, 7 runs. Example 2 stops at index 4, after 5 runs.

  4. 4 Keep only the part that grows fastest

    There is nothing to drop. The count is already n.

    So the time is O(n).

  5. S Space: count the extra memory the same way

    The code keeps reach and i. The space is O(1).

    reachi

2,000 random arrays of 1 to 10 jumps from 0 to 3, with many zeros, so traps and ends reached just barely both come up. Mark reachable cells and greedy reach gave the same answer every time.

Largest inputsResult
10,000 ones (the most allowed), so every index is read. Greedy reach. Also run with a 0 just before the end, a trap at the last step.Under 0.001 s, and under 0.001 MB of extra memory: just reach and i.
2,000 jumps of 100,000 each. Mark reachable cells.0.03 s, and about 0.02 MB for the flags. Long jumps make it mark about 2 million cells. At 10,000 it would mark about 50 million.