You are given an array of integers nums, where nums[i] represents the maximum length of a jump towards the right from index i. For example, if you are at nums[i], you can jump to any index i + j where:
j <= nums[i]i + j < nums.lengthYou are initially positioned at nums[0].
Return the minimum number of jumps to reach the last position in the array (index nums.length - 1). You may assume there is always a valid answer.
Example 1:
Input: nums = [2,4,1,1,1,1]
Output: 2Explanation: Jump from index 0 to index 1, then jump from index 1 to the last index.
Example 2:
Input: nums = [2,1,2,1,0]
Output: 2Constraints:
1 <= nums.length <= 10000 <= nums[i] <= 100
You should aim for a solution with O(n) time and O(1) space, where n is the size of the input array.
A brute force approach would be to recursively explore all paths from index 0 to its reachable indices, then process those indices similarly and return the minimum steps to reach the last index. This would be an exponential approach. Can you think of a better way? Maybe a greedy approach works.
We maintain two pointers, l and r, initially set to 0, representing the range of reachable indices. At each step, we iterate through the indices in the range l to r and determine the farthest index that can be reached from the current range.
We then update the pointers l and r to the next range, setting l to r + 1 and r to the farthest index reachable from the current range. We continue this process until the pointers go out of bounds.
The number of steps taken represents the minimum steps required to reach the last index, as it is guaranteed that we can reach it.
Before attempting this problem, you should be comfortable with:
This problem asks for the minimum number of jumps needed to reach the last index of the array.
From any index i, the value nums[i] tells us how far we can jump.
So at index i, we can choose to jump to any index between i + 1 and i + nums[i].
Using recursion, we try all possible jumps from the current index and choose the one that leads to the end using the fewest total jumps.
The recursive function represents:
"What is the minimum number of jumps required to reach the last index starting from index i?"
If we ever reach the last index, no more jumps are needed.
If we get stuck at an index with 0 jump length, that path is invalid.
dfs(i):i is the current indexi is already the last index:0 because no more jumps are needednums[i] == 0:end = min(last_index, i + nums[i])res to infinityi + 1 to end:j, compute 1 + dfs(j)res with the minimum value foundres as the minimum jumps needed from index i0 and return the resultclass Solution:
def jump(self, nums: List[int]) -> int:
def dfs(i):
if i == len(nums) - 1:
return 0
if nums[i] == 0:
return float('inf')
end = min(len(nums) - 1, i + nums[i])
res = float('inf')
for j in range(i + 1, end + 1):
res = min(res, 1 + dfs(j))
return res
return dfs(0)This problem asks for the minimum number of jumps required to reach the last index.
At any index i, the value nums[i] tells us the maximum jump length from that position.
So from index i, we can try jumping to any index in the range (i + 1) to (i + nums[i]).
The pure recursive solution tries all possibilities, but it recomputes the same results for the same indices many times.
To avoid this repetition, we use top-down dynamic programming (memoization).
The recursive function answers the question:
"What is the minimum number of jumps needed to reach the end starting from index i?"
Once we compute the answer for an index, we store it and reuse it whenever needed.
memo:memo[i] stores the minimum jumps needed to reach the end from index idfs(i):i is the current indexi is already in memo:i is the last index:0 since no more jumps are requirednums[i] == 0:ij, compute 1 + dfs(j)memo[i] and return it0class Solution:
def jump(self, nums: List[int]) -> int:
memo = {}
def dfs(i):
if i in memo:
return memo[i]
if i == len(nums) - 1:
return 0
if nums[i] == 0:
return 1000000
res = 1000000
end = min(len(nums), i + nums[i] + 1)
for j in range(i + 1, end):
res = min(res, 1 + dfs(j))
memo[i] = res
return res
return dfs(0)This problem asks for the minimum number of jumps needed to reach the last index of the array.
Instead of using recursion, we can solve this using bottom-up dynamic programming by working backwards from the end.
The key idea is:
i, we want to know the minimum number of jumps needed to reach the end starting from ii, we can jump to any index in the range [i + 1, i + nums[i]]i is: 1 + minimum(dp[j]) for all reachable jBy filling the DP array from right to left, all future states are already computed when needed.
n be the length of the array.dp of size n:dp[i] represents the minimum number of jumps needed to reach the last index from index idp[n - 1] = 0 since we are already at the last indexi from n - 2 down to 0:i:end = min(n, i + nums[i] + 1)j from i + 1 to end - 1dp[i] = min(dp[i], 1 + dp[j])dp[0] contains the minimum number of jumps from the startdp[0]This problem asks for the minimum number of jumps needed to reach the last index.
We can think of this problem as moving level by level, similar to Breadth First Search (BFS):
Instead of explicitly using a queue, we use a greedy window:
[l, r] represents the range of indices reachable with the current number of jumpsOnce we finish scanning the current range, we move to the next range and increase the jump count.
res = 0 to count the number of jumpsl = 0, r = 0 to represent the current reachable ranger has not reached the last index:i in the current range [l, r]:farthest = max(i + nums[i])l = r + 1, r = farthestresresA common mistake is to always jump to i + nums[i] (the farthest reachable position). This greedy choice does not guarantee the minimum number of jumps. Instead, you should consider all positions reachable from the current range and pick the one that maximizes your reach for the next jump.
When implementing the BFS-style greedy solution, the window [l, r] represents the current level of reachable positions. Incorrectly updating l or r after processing a level can cause positions to be skipped or processed multiple times, leading to wrong jump counts.
If nums[i] == 0, you cannot make progress from position i. In recursive or DP solutions, this should return infinity (or a large value) to indicate an invalid path. Forgetting this check can cause incorrect results when a path leads to a dead end.