class Solution:
def maxJumps(self, arr, d):
n = len(arr)
dp = [0] * n
def dfs(i):
if dp[i]:
return dp[i]
max_jump = 1
# Left
for j in range(i-1, max(i-d-1, -1), -1):
if arr[j] >= arr[i]:
break
max_jump = max(max_jump, 1 + dfs(j))
# Right
for j in range(i+1, min(i+d+1, n)):
if arr[j] >= arr[i]:
break
max_jump = max(max_jump, 1 + dfs(j))
dp[i] = max_jump
return max_jump
return max(dfs(i) for i in range(n))
class Solution {
public:
int maxJumps(vector<int>& arr, int d) {
int n = arr.size();
vector<int> dp(n, 0);
function<int(int)> dfs = [&](int i) {
if (dp[i]) return dp[i];
int max_jump = 1;
// Left
for (int j = i - 1; j >= max(i - d, 0); --j) {
if (arr[j] >= arr[i]) break;
max_jump = max(max_jump, 1 + dfs(j));
}
// Right
for (int j = i + 1; j <= min(i + d, n - 1); ++j) {
if (arr[j] >= arr[i]) break;
max_jump = max(max_jump, 1 + dfs(j));
}
dp[i] = max_jump;
return max_jump;
};
int res = 0;
for (int i = 0; i < n; ++i) {
res = max(res, dfs(i));
}
return res;
}
};
class Solution {
public int maxJumps(int[] arr, int d) {
int n = arr.length;
int[] dp = new int[n];
int res = 0;
for (int i = 0; i < n; ++i) {
res = Math.max(res, dfs(arr, d, dp, i));
}
return res;
}
private int dfs(int[] arr, int d, int[] dp, int i) {
if (dp[i] != 0) return dp[i];
int max_jump = 1;
// Left
for (int j = i - 1; j >= Math.max(i - d, 0); --j) {
if (arr[j] >= arr[i]) break;
max_jump = Math.max(max_jump, 1 + dfs(arr, d, dp, j));
}
// Right
for (int j = i + 1; j <= Math.min(i + d, arr.length - 1); ++j) {
if (arr[j] >= arr[i]) break;
max_jump = Math.max(max_jump, 1 + dfs(arr, d, dp, j));
}
dp[i] = max_jump;
return max_jump;
}
}
var maxJumps = function(arr, d) {
const n = arr.length;
const dp = new Array(n).fill(0);
function dfs(i) {
if (dp[i]) return dp[i];
let max_jump = 1;
// Left
for (let j = i - 1; j >= Math.max(i - d, 0); --j) {
if (arr[j] >= arr[i]) break;
max_jump = Math.max(max_jump, 1 + dfs(j));
}
// Right
for (let j = i + 1; j <= Math.min(i + d, n - 1); ++j) {
if (arr[j] >= arr[i]) break;
max_jump = Math.max(max_jump, 1 + dfs(j));
}
dp[i] = max_jump;
return max_jump;
}
let res = 0;
for (let i = 0; i < n; ++i) {
res = Math.max(res, dfs(i));
}
return res;
};
Given an array arr
of positive integers and an integer d
, you start at any index and can jump left or right up to d
steps. However, you can only jump to indices with a strictly lower value than your current index, and you must stop jumping in a direction if you encounter a value greater than or equal to your starting value.
Your goal is to find the maximum number of indices you can visit starting from any index, counting the starting index itself. Each index may be visited only once in each path, and you must not revisit elements.
Constraints:
arr.length
≤ 1000arr[i]
≤ 105d
≤ arr.lengthAt first glance, the problem seems to ask for the longest path you can take by jumping from each index, following the rules. A brute-force approach would be to try every possible path from every index, but this quickly becomes inefficient as the array grows.
The key insight is that the problem exhibits overlapping subproblems: the maximum number of jumps from a given index depends only on the results from its potential next jumps. Thus, we can use memoization (dynamic programming) to store results and avoid redundant calculations.
The process is similar to exploring all possible moves in a game, but with the added restriction that you can only move to strictly lower values and must stop when you hit a higher or equal value. This makes the problem ideal for a depth-first search (DFS) with memoization.
i
, let dp[i]
be the maximum number of indices you can visit starting from i
.
d
steps), but only to strictly lower values, and stops if a higher or equal value is encountered.
dp[i]
so that each index is only computed once, ensuring efficient computation.
Suppose arr = [6, 4, 14, 6, 8, 13, 9, 7, 10, 6, 12]
and d = 2
.
This process is repeated for each starting index, and the overall maximum is returned.
2d
possible moves (left and right). Thus, the time complexity is O(n * d).
The approach is efficient for the given constraints.
The key to solving Jump Game V is recognizing overlapping subproblems and using memoization to avoid recomputation. By using DFS to explore all valid jumps from each index and caching results, we efficiently find the longest possible path from any starting point. This approach leverages dynamic programming principles and is both elegant and practical for the problem's constraints.