The problem
You start at index 0 of an array nums of non-negative integers. nums[i] is the maximum jump length from index i; you may jump any distance from 0 up to that. Return True if you can reach the last index, otherwise False.
Input: nums = [2, 3, 1, 1, 4]
Output: True
Input: nums = [3, 2, 1, 0, 4]
Output: FalseIn the first, jump 0 → 1 → 4. In the second, every path lands on index 3, whose value is 0, so index 4 is out of reach.
How to think about it
Start with brute force. From each index, try every jump length and recurse. That explores an exponential number of paths. A DP version marks good[i] = “can reach the end from i” by checking every jump from i, which is O(n²) in the worst case.
The key insight: reachable indices form one solid block. If you can reach index j, you can also reach every index before it, because jumps can be any length up to the maximum. So the whole set of reachable indices is just 0..reach. You never need a table of booleans, only one number: the furthest index reachable so far.
Scan and extend. Walk left to right. At index i, if i > reach, then i and everything after it is unreachable, so return False. Otherwise i is reachable, and from it you can get to i + nums[i], so reach = max(reach, i + nums[i]). If the scan finishes, the last index was reachable.
Which pattern is this? A 1-D reachability DP that collapses into a greedy scan. The tell is “can you reach the end” with variable jump lengths: the DP state shrinks to a single running maximum. The same idea appears in the greedy lesson.
Approach
- Set
reach = 0. - For each index
iwith valuex:- If
i > reach, returnFalse(you can’t stand here). - Otherwise set
reach = max(reach, i + x).
- If
- If the loop ends, return
True.
Solution
def can_jump(nums):
reach = 0 # furthest index reachable so far
for i, x in enumerate(nums):
if i > reach: return False # this index is beyond reach: stuck
reach = max(reach, i + x) # extend the reachable block
return True
# can_jump([2,3,1,1,4]) -> True ; can_jump([3,2,1,0,4]) -> FalseDry run
On [3, 2, 1, 0, 4] (the failing case):
i |
nums[i] |
i > reach? |
reach after |
|---|---|---|---|
| 0 | 3 | no | 3 |
| 1 | 2 | no | 3 |
| 2 | 1 | no | 3 |
| 3 | 0 | no | 3 |
| 4 | 4 | yes (4 > 3) | return False |
On [2, 3, 1, 1, 4], reach goes 2, 4, 4, 4, 8 and the loop finishes, so it returns True.
Complexity
- Time: O(n). One pass, constant work per index.
- Space: O(1). A single integer replaces the
good[]table.
Edge cases and pitfalls
- Single element (
[0]) returnsTrue: you are already at the last index. - Zeros are only traps if you can’t jump over them.
[2, 0, 0]isTruebecause index 0 reaches index 2 directly. - Early exit. You can return
Trueas soon asreach >= len(nums) - 1; it’s an optimisation, not a correctness fix. - Greedily taking the longest jump from each spot is wrong; tracking the furthest reach over all visited spots is what makes it correct.
Related problems
- Jump Game II (LeetCode 45): you can always reach the end; find the fewest jumps with the same furthest-reach idea.
- Gas Station (LeetCode 134): another one-pass greedy that replaces an O(n²) simulation.
- Climbing Stairs (LeetCode 70): the counting cousin, where each step reaches a fixed distance ahead.
- 1.Climbing Stairs (LeetCode 70)
- 2.Min Cost Climbing Stairs (LeetCode 746)
- 3.Maximum Subarray (LeetCode 53)
- 4.House Robber (LeetCode 198)
- 5.House Robber II (LeetCode 213)
- 6.Jump Game (LeetCode 55)
- 7.Coin Change (LeetCode 322)
- 8.Coin Change II (LeetCode 518)
- 9.Word Break (LeetCode 139)
- 10.Decode Ways (LeetCode 91)
- 11.Maximum Product Subarray (LeetCode 152)
- 12.Longest Increasing Subsequence (LeetCode 300)
- 13.Partition Equal Subset Sum (LeetCode 416)