59 - Jump Game
You are given an integer array nums where each element nums[i] indicates your maximum jump length at that position.
Return true if you can reach the last index starting from index 0, or false otherwise.
Examples¶
Example 1
Input: nums = [1,2,0,1,0]
Output: true
Explanation: First jump from index 0 to 1, then from index 1 to 3, and lastly from index 3 to 4.
Example 2
Input: nums = [1,2,1,0,1]
Output: false
Solution¶
Java Code¶
class Solution {
public boolean canJump(int[] nums) {
// We start from the last index as our initial goal
int goal = nums.length - 1;
// Iterate backwards from the second-to-last element to the first
for (int i = nums.length - 2; i >= 0; i--) {
// If we can reach the current 'goal' from position 'i'
if (i + nums[i] >= goal) {
// Update the goal to 'i'
goal = i;
}
}
// If the goal reaches index 0, then we can reach the end
return goal == 0;
}
}
Intuition¶
The problem asks if it's possible to reach the end. While this can be solved with Dynamic Programming or BFS, a Greedy approach is the most efficient.
Greedy Strategy¶
Instead of starting from the beginning and trying every jump (forward), we move backwards from the goal. - We want to reach the end. Can the element before it reach the end? If yes, then our "new" goal becomes reaching that element. - We keep shifting the target index closer to the start whenever we find a position from which we can jump to the current goal.
If at the end of the traversal the goal has reached the very first index (0), it means there is a path from 0 to the original last index.
Complexity Analysis¶
Time Complexity¶
\(O(n)\)
- We traverse the array exactly once from right to left.
Space Complexity¶
\(O(1)\)
- We only use a single variable
goalto track the target position.
Key Takeaways¶
- Greedy works here because if we can reach an index \(i\) that can reach the goal, we don't care how we reaches \(i\); we just need to know \(i\) is attainable.
- Backward iteration often simplifies "reachability" problems compared to forward simulation.
- This is significantly more efficient than a \(O(n^2)\) DP solution where \(dp[i]\) tracks if index \(i\) is reachable.