Jump Game V

hard dynamic programming array sorting

Problem

Given an array arr and an integer d, from index i you may jump to i ± x for 1 ≤ x ≤ d (staying in bounds) only if every bar strictly between i and the target is shorter than arr[i], and the target itself is shorter than arr[i]. Starting from any index, return the maximum number of indices you can visit.

Inputarr = [6,4,14,6,8,13,9,7,10,6,12], d = 2
Output4
Start at index 10 and jump 10 → 8 → 6 → 7, visiting 4 indices.

def maxJumps(arr, d):
    n = len(arr)
    dp = [0] * n                       # dp[i] = best visits starting at i
    order = sorted(range(n), key=lambda i: arr[i])  # shortest bars first
    for i in order:
        best = 0
        for j in range(i + 1, min(n, i + d + 1)):   # scan right
            if arr[j] >= arr[i]:
                break                  # blocked by a tall/equal bar
            best = max(best, dp[j])
        for j in range(i - 1, max(-1, i - d - 1), -1):  # scan left
            if arr[j] >= arr[i]:
                break
            best = max(best, dp[j])
        dp[i] = 1 + best               # this index plus the best reachable
    return max(dp)
function maxJumps(arr, d) {
  const n = arr.length;
  const dp = new Array(n).fill(0);          // dp[i] = best visits from i
  const order = [...arr.keys()].sort((a, b) => arr[a] - arr[b]);
  for (const i of order) {                  // shortest bars first
    let best = 0;
    for (let j = i + 1; j < Math.min(n, i + d + 1); j++) {
      if (arr[j] >= arr[i]) break;           // blocked to the right
      best = Math.max(best, dp[j]);
    }
    for (let j = i - 1; j > Math.max(-1, i - d - 1); j--) {
      if (arr[j] >= arr[i]) break;           // blocked to the left
      best = Math.max(best, dp[j]);
    }
    dp[i] = 1 + best;                        // include i itself
  }
  return Math.max(...dp);
}
int maxJumps(int[] arr, int d) {
    int n = arr.length;
    int[] dp = new int[n];                   // dp[i] = best visits from i
    Integer[] order = new Integer[n];
    for (int i = 0; i < n; i++) order[i] = i;
    Arrays.sort(order, (a, b) -> arr[a] - arr[b]);  // shortest first
    int ans = 0;
    for (int i : order) {
        int best = 0;
        for (int j = i + 1; j < Math.min(n, i + d + 1); j++) {
            if (arr[j] >= arr[i]) break;     // blocked to the right
            best = Math.max(best, dp[j]);
        }
        for (int j = i - 1; j > Math.max(-1, i - d - 1); j--) {
            if (arr[j] >= arr[i]) break;     // blocked to the left
            best = Math.max(best, dp[j]);
        }
        dp[i] = 1 + best;
        ans = Math.max(ans, dp[i]);
    }
    return ans;
}
int maxJumps(vector<int>& arr, int d) {
    int n = arr.size();
    vector<int> dp(n, 0);                     // dp[i] = best visits from i
    vector<int> order(n);
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(),
         [&](int a, int b){ return arr[a] < arr[b]; });  // shortest first
    int ans = 0;
    for (int i : order) {
        int best = 0;
        for (int j = i + 1; j < min(n, i + d + 1); j++) {
            if (arr[j] >= arr[i]) break;     // blocked to the right
            best = max(best, dp[j]);
        }
        for (int j = i - 1; j > max(-1, i - d - 1); j--) {
            if (arr[j] >= arr[i]) break;     // blocked to the left
            best = max(best, dp[j]);
        }
        dp[i] = 1 + best;
        ans = max(ans, dp[i]);
    }
    return ans;
}
Time: O(n log n + n · d) Space: O(n)