Jump Game II(LeetCode)
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]
andi + j < n
Return the minimum number of jumps to reachnums[n - 1]
. The test cases are generated such that you can reachnums[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
Constraints​
1 <= nums.length <= 104
0 <= nums[i] <= 1000
- It's guaranteed that you can reach
nums[n - 1]
.
Solution​
In this problem, we aim to find the minimum number of jumps required to reach the end of the array, starting from the first element. We explore three main approaches: Recursive Dynamic Programming with Memoization, Iterative Dynamic Programming with Tabulation, and a Greedy BFS approach.
Approach 1: Recursive Dynamic Programming (Memoization)​
Concept: Store the solutions for each position to avoid redundant calculations.
Algorithm​
- Initialize
dp
array with a large value to indicate uncomputed positions. - Call the recursive function
solve
starting from position 0. - In
solve
:
- If the position is at or beyond the end, return 0.
- If
dp[pos]
is already computed, return its value. - Explore all possible jumps from the current position.
- Store and return the minimum jumps required.
Implementation​
int jump(vector<int>& nums) {
vector<int> dp(size(nums), 10001);
return solve(nums, dp, 0);
}
int solve(vector<int>& nums, vector<int>& dp, int pos) {
if(pos >= size(nums) - 1) return 0;
if(dp[pos] != 10001) return dp[pos];
for(int j = 1; j <= nums[pos]; j++)
dp[pos] = min(dp[pos], 1 + solve(nums, dp, pos + j));
return dp[pos];
}
Complexity Analysis​
- Time complexity: O(N^2)
- Space complexity: O(N)
Approach 2: Iterative Dynamic Programming (Tabulation)​
Concept: Start from the last index and iteratively compute the minimum jumps required for each position.
Algorithm​
- Initialize
dp
array with large values and setdp[n-1]
to 0. - Iterate from the second last index to the start.
- For each index, explore all possible jumps and store the minimum jumps required.
Implementation​
int jump(vector<int>& nums) {
int n = size(nums);
vector<int> dp(n, 10001);
dp[n - 1] = 0;
for(int i = n - 2; i >= 0; i--)
for(int jumpLen = 1; jumpLen <= nums[i]; jumpLen++)
dp[i] = min(dp[i], 1 + dp[min(n - 1, i + jumpLen)]);
return dp[0];
}
Complexity Analysis​
- Time complexity: O(N^2)
- Space complexity: O(N)
Approach 3: Greedy BFS​
Concept: Use two pointers to track the furthest reachable position and the currently furthest reached position. Update the jump count when moving to a new level.
Algorithm​
- Initialize
maxReachable
,lastJumpedPos
, andjumps
. - Iterate over the array until the lastJumpedPos reaches or exceeds the last index.
- Update
maxReachable
with the furthest position reachable from the current index. - When
i
equalslastJumpedPos
, move tomaxReachable
and increment jumps.
Implementation​
int jump(vector<int>& nums) {
int n = size(nums), i = 0, maxReachable = 0, lastJumpedPos = 0, jumps = 0;
while(lastJumpedPos < n - 1) {
maxReachable = max(maxReachable, i + nums[i]);
if(i == lastJumpedPos) {
lastJumpedPos = maxReachable;
jumps++;
}
i++;
}
return jumps;
}
Complexity Analysis​
- Time complexity: O(N)
- Space complexity: O(1)
Conclusion​
- Recursive DP with Memoization: Efficiently avoids redundant calculations but has higher time complexity.
- Iterative DP with Tabulation: Iteratively solves for each position but has quadratic time complexity.
- Greedy BFS: Provides the most optimal solution with linear time complexity and constant space, making it the best approach for this problem.