Language Selection
Choose your preferred programming language
Jump Game II
Problem Statement
You are given a 0-indexed array of integers nums of length n. You are initially positioned at nums[0].
Each element nums[i] represents the maximum length of a forward jump from index i. In other words, if you are at nums[i], you can jump to any nums[i + j] where 0 <= j <= nums[i] and i + j < n.
Return the minimum number of jumps to reach nums[n - 1]. The test cases are generated such that you can always reach nums[n - 1].
Constraints:
1 <= nums.length <= 10^40 <= nums[i] <= 1000- It is guaranteed that you can reach
nums[n - 1]
Examples:
Example 1:
Input: nums = [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:
Input: nums = [2,3,0,1,4]
Output: 2
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 3:
Input: nums = [1,1,1,1]
Output: 3
Explanation: Jump 1 step at a time: 0 -> 1 -> 2 -> 3.
Example 4:
Input: nums = [10,1,1,1,1]
Output: 1
Explanation: Jump directly from index 0 to index 4.
Approach 1: BFS (Level-Order Traversal)
Algorithm:
- Treat the array as a graph where each index can reach a range of subsequent indices
- Perform BFS where each “level” represents one jump
- For each level, find the furthest index reachable from all positions in the current level
- The number of levels traversed to reach the last index is the answer
Time Complexity: O(n) Space Complexity: O(1)
Python:
def jump(nums):
"""
Find minimum jumps using BFS level-order traversal
Time: O(n)
Space: O(1)
"""
n = len(nums)
if n <= 1:
return 0
jumps = 0
current_end = 0 # end of current BFS level
farthest = 0 # farthest reachable from current level
for i in range(n - 1):
farthest = max(farthest, i + nums[i])
if i == current_end:
jumps += 1
current_end = farthest
if current_end >= n - 1:
break
return jumps
Java:
class Solution {
/**
* Find minimum jumps using BFS level-order traversal
* Time: O(n)
* Space: O(1)
*/
public int jump(int[] nums) {
int n = nums.length;
if (n <= 1) return 0;
int jumps = 0;
int currentEnd = 0;
int farthest = 0;
for (int i = 0; i < n - 1; i++) {
farthest = Math.max(farthest, i + nums[i]);
if (i == currentEnd) {
jumps++;
currentEnd = farthest;
if (currentEnd >= n - 1) {
break;
}
}
}
return jumps;
}
}
Go:
// jump - Find minimum jumps using BFS level-order traversal
// Time: O(n)
// Space: O(1)
func jump(nums []int) int {
n := len(nums)
if n <= 1 {
return 0
}
jumps := 0
currentEnd := 0
farthest := 0
for i := 0; i < n-1; i++ {
if i+nums[i] > farthest {
farthest = i + nums[i]
}
if i == currentEnd {
jumps++
currentEnd = farthest
if currentEnd >= n-1 {
break
}
}
}
return jumps
}
JavaScript:
/**
* Find minimum jumps using BFS level-order traversal
* Time: O(n)
* Space: O(1)
*/
function jump(nums) {
const n = nums.length;
if (n <= 1) return 0;
let jumps = 0;
let currentEnd = 0;
let farthest = 0;
for (let i = 0; i < n - 1; i++) {
farthest = Math.max(farthest, i + nums[i]);
if (i === currentEnd) {
jumps++;
currentEnd = farthest;
if (currentEnd >= n - 1) {
break;
}
}
}
return jumps;
}
C#:
public class Solution {
/// <summary>
/// Find minimum jumps using BFS level-order traversal
/// Time: O(n)
/// Space: O(1)
/// </summary>
public int Jump(int[] nums) {
int n = nums.Length;
if (n <= 1) return 0;
int jumps = 0;
int currentEnd = 0;
int farthest = 0;
for (int i = 0; i < n - 1; i++) {
farthest = Math.Max(farthest, i + nums[i]);
if (i == currentEnd) {
jumps++;
currentEnd = farthest;
if (currentEnd >= n - 1) {
break;
}
}
}
return jumps;
}
}
Approach 2: Greedy (Forward Scanning)
Algorithm:
- At each jump, scan all positions reachable from the current position
- Among those positions, pick the one that lets us reach the furthest after the next jump
- This greedy choice guarantees minimizing total jumps
- Continue until we reach or exceed the last index
Time Complexity: O(n) Space Complexity: O(1)
Python:
def jump(nums):
"""
Find minimum jumps using forward-scanning greedy
Time: O(n)
Space: O(1)
"""
n = len(nums)
if n <= 1:
return 0
jumps = 0
pos = 0
while pos < n - 1:
# If current position can reach the end directly
if pos + nums[pos] >= n - 1:
jumps += 1
break
# Find the next position that maximizes reach
best_next = pos + 1
best_reach = 0
for i in range(pos + 1, min(pos + nums[pos] + 1, n)):
if i + nums[i] > best_reach:
best_reach = i + nums[i]
best_next = i
pos = best_next
jumps += 1
return jumps
Java:
class Solution {
/**
* Find minimum jumps using forward-scanning greedy
* Time: O(n)
* Space: O(1)
*/
public int jump(int[] nums) {
int n = nums.length;
if (n <= 1) return 0;
int jumps = 0;
int pos = 0;
while (pos < n - 1) {
if (pos + nums[pos] >= n - 1) {
jumps++;
break;
}
int bestNext = pos + 1;
int bestReach = 0;
for (int i = pos + 1; i <= Math.min(pos + nums[pos], n - 1); i++) {
if (i + nums[i] > bestReach) {
bestReach = i + nums[i];
bestNext = i;
}
}
pos = bestNext;
jumps++;
}
return jumps;
}
}
Go:
// jump - Find minimum jumps using forward-scanning greedy
// Time: O(n)
// Space: O(1)
func jump(nums []int) int {
n := len(nums)
if n <= 1 {
return 0
}
jumps := 0
pos := 0
for pos < n-1 {
if pos+nums[pos] >= n-1 {
jumps++
break
}
bestNext := pos + 1
bestReach := 0
end := pos + nums[pos]
if end > n-1 {
end = n - 1
}
for i := pos + 1; i <= end; i++ {
if i+nums[i] > bestReach {
bestReach = i + nums[i]
bestNext = i
}
}
pos = bestNext
jumps++
}
return jumps
}
JavaScript:
/**
* Find minimum jumps using forward-scanning greedy
* Time: O(n)
* Space: O(1)
*/
function jump(nums) {
const n = nums.length;
if (n <= 1) return 0;
let jumps = 0;
let pos = 0;
while (pos < n - 1) {
if (pos + nums[pos] >= n - 1) {
jumps++;
break;
}
let bestNext = pos + 1;
let bestReach = 0;
for (let i = pos + 1; i <= Math.min(pos + nums[pos], n - 1); i++) {
if (i + nums[i] > bestReach) {
bestReach = i + nums[i];
bestNext = i;
}
}
pos = bestNext;
jumps++;
}
return jumps;
}
C#:
public class Solution {
/// <summary>
/// Find minimum jumps using forward-scanning greedy
/// Time: O(n)
/// Space: O(1)
/// </summary>
public int Jump(int[] nums) {
int n = nums.Length;
if (n <= 1) return 0;
int jumps = 0;
int pos = 0;
while (pos < n - 1) {
if (pos + nums[pos] >= n - 1) {
jumps++;
break;
}
int bestNext = pos + 1;
int bestReach = 0;
for (int i = pos + 1; i <= Math.Min(pos + nums[pos], n - 1); i++) {
if (i + nums[i] > bestReach) {
bestReach = i + nums[i];
bestNext = i;
}
}
pos = bestNext;
jumps++;
}
return jumps;
}
}
Key Insights
BFS Analogy: Each jump corresponds to a BFS level. Positions reachable in 1 jump form level 1, positions reachable in 2 jumps form level 2, and so on. The first level that contains the last index gives the minimum jumps.
Implicit BFS without Queue: By tracking
currentEnd(boundary of current level) andfarthest(boundary of next level), we simulate BFS without a queue, achieving O(1) space.Greedy Correctness: At each step, extending to the farthest reachable position is optimal because it maximizes future options. Any other choice can only do worse or equal.
Loop Boundary: Iterating up to
n - 2(notn - 1) avoids counting an extra jump when we are already at or past the last index at the end of a level.Guaranteed Reachability: The problem guarantees a solution exists, so we never need to handle the case where the last index is unreachable.
Edge Cases
- Single element:
[0]→0(already at the last index) - Two elements:
[1,0]→1(one jump from index 0 to index 1) - Direct reach:
[10,1,1,1,1]→1(first element can jump past the end) - All ones:
[1,1,1,1]→3(must jump one step at a time) - Large first, small rest:
[5,1,1,1,1,1]→1 - Zigzag values:
[2,1,3,1,1]→2
Test Cases
# Test case 1: Standard case
assert jump([2,3,1,1,4]) == 2
# Test case 2: With zeros
assert jump([2,3,0,1,4]) == 2
# Test case 3: All ones
assert jump([1,1,1,1]) == 3
# Test case 4: Single element
assert jump([0]) == 0
# Test case 5: Direct jump to end
assert jump([10,1,1,1,1]) == 1
# Test case 6: Two elements
assert jump([1,0]) == 1
# Test case 7: Optimal path not obvious
assert jump([1,2,3]) == 2
# Test case 8: Large jumps throughout
assert jump([5,4,3,2,1,1]) == 2
Common Mistakes
Iterating to
n - 1instead ofn - 2: In the BFS approach, iterating to the last index can add an unnecessary jump whencurrentEndalready covers the last index.Not handling single element arrays: An array of length 1 needs 0 jumps since you start at the last index.
Confusing Jump Game I with Jump Game II: Jump Game I asks if you can reach the end (boolean), while Jump Game II asks for the minimum number of jumps (integer). The greedy structure is similar but the tracking differs.
Greedy scanning past array bounds: When scanning reachable positions, forgetting to cap the range at
n - 1causes index-out-of-bounds errors.Not breaking early: When
farthestorcurrentEndalready exceedsn - 1, failing to break out of the loop may count extra iterations (though it typically does not change the answer in the BFS approach).