Approach Summary
Track max reachable index. If current index exceeds max reachable, return false. Update max at each step.
Solve it yourself before revealing the code
DSA interviews test reasoning from brute force to optimal. Think through the constraints first.
Solution Progression (Brute Force → Most Optimized)
Understand the architectural evolution from naive baseline to optimal complexity.
| Approach | Time | Space | Core Strategy / Trade-off |
|---|---|---|---|
| 1 Approach 1: Backward Greedy Target Shift | O(n) | O(1) | Work backwards from destination n - 1, shifting target to i whenever i + nums[i] >= target. |
| 2 Approach 2: Forward Greedy Maximum Reach (Optimal) | O(n) | O(1) | Track max reachable boundary as you iterate forward, failing early if current index > maxReachable. |
Approach 1: Backward Greedy Target Shift
Set destination target = n - 1. Iterate backwards from n - 2 down to 0. If index i can jump to or beyond target (i + nums[i] >= target), update target = i. If target successfully reaches index 0 by the end of the loop, a valid path exists.
Approach 1: Backward Greedy Target Shift Implementation
Approach 1: Backward Greedy Target Shift
class Solution {
public boolean canJump(int[] nums) {
int target = nums.length - 1;
for (int i = nums.length - 2; i >= 0; i--) {
if (i + nums[i] >= target) {
target = i;
}
}
return target == 0;
}
}class Solution {
public:
bool canJump(vector<int>& nums) {
int target = nums.size() - 1;
for (int i = nums.size() - 2; i >= 0; i--) {
if (i + nums[i] >= target) {
target = i;
}
}
return target == 0;
}
};class Solution:
def canJump(self, nums: list[int]) -> bool:
target = len(nums) - 1
for i in range(len(nums) - 2, -1, -1):
if i + nums[i] >= target:
target = i
return target == 0function canJump(nums) {
let target = nums.length - 1;
for (let i = nums.length - 2; i >= 0; i--) {
if (i + nums[i] >= target) {
target = i;
}
}
return target === 0;
} Approach 2: Forward Greedy Maximum Reach (Optimal)
Keep maxReachable = 0. For each index i, if maxReachable < i, you are stranded and cannot proceed. Otherwise, update maxReachable = max(maxReachable, i + nums[i]). If at any point maxReachable >= n - 1, the destination is reachable.
Approach 2: Forward Greedy Maximum Reach (Optimal) Implementation
Approach 2: Forward Greedy Maximum Reach (Optimal)
class Solution {
public boolean canJump(int[] nums) {
int n = nums.length;
int maxReachable = 0;
for (int i = 0; i < n; i++) {
if (maxReachable < i) {
return false;
}
maxReachable = Math.max(maxReachable, i + nums[i]);
}
return true;
}
}class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int maxReachable = 0;
for (int i = 0; i < n; i++) {
if (maxReachable < i) {
return false;
}
maxReachable = max(maxReachable, i + nums[i]);
}
return true;
}
};class Solution:
def canJump(self, nums: list[int]) -> bool:
max_reachable = 0
for i, val in enumerate(nums):
if i > max_reachable:
return False
max_reachable = max(max_reachable, i + val)
return Truefunction canJump(nums) {
let maxReachable = 0;
for (let i = 0; i < nums.length; i++) {
if (i > maxReachable) return false;
maxReachable = Math.max(maxReachable, i + nums[i]);
}
return true;
} Edge Cases to Watch
- Single element array (e.g. nums = [0]; already at destination, returns true)
- Zero preventing progress (e.g. [3, 2, 1, 0, 4]; cannot jump past index 3, returns false)
- Large jump from start (e.g. [5, 0, 0, 0, 0]; can jump directly to end, returns true)
- Zero at intermediate position but easily jumped over (e.g. [2, 0, 0]; returns true)
Master the Greedy Pattern
Study the core invariant, step-by-step decision framework, and common interview traps for the Greedy pattern.
How to Recognize This Pattern
- Can you reach the end?
- Greedy max reach
Complexity Analysis
Time Complexity
O(n)
Space Complexity
O(1)