Back to all solutions

#975 - Odd Even Jump

Problem Description

You are given an integer array arr. From some starting index, you can make a series of jumps.

The (1st, 3rd, 5th, ...) jumps in the series are called odd-numbered jumps, and the (2nd, 4th, 6th, ...) jumps in the series are called even-numbered jumps. Note that the jumps are numbered, not the indices.

You may jump forward from index i to index j (with i < j) in the following way:

  • During odd-numbered jumps (i.e., jumps 1, 3, 5, ...), you jump to the index j such that arr[i] <= arr[j] and arr[j] is the smallest possible value. If there are multiple such indices j, you can only jump to the smallest such index j.
  • During even-numbered jumps (i.e., jumps 2, 4, 6, ...), you jump to the index j such that arr[i] >= arr[j] and arr[j] is the largest possible value. If there are multiple such indices j, you can only jump to the smallest such index j.
  • It may be the case that for some index i, there are no legal jumps.

A starting index is good if, starting from that index, you can reach the end of the array (index arr.length - 1) by jumping some number of times (possibly 0 or more than once).

Return the number of good starting indices.

Solution

/**
 * @param {number[]} arr
 * @return {number}
 */
var oddEvenJumps = function(arr) {
  const oddCanReach = new Array(arr.length).fill(false);
  const evenCanReach = new Array(arr.length).fill(false);
  oddCanReach[arr.length - 1] = true;
  evenCanReach[arr.length - 1] = true;
  let result = 1;

  const sortedIndices = Array.from({ length: arr.length }, (_, i) => i);
  sortedIndices.sort((a, b) => arr[a] - arr[b] || a - b);

  const oddNext = new Array(arr.length);
  const evenNext = new Array(arr.length);
  const stack = [];

  for (const i of sortedIndices) {
    while (stack.length && stack[stack.length - 1] < i) {
      oddNext[stack.pop()] = i;
    }
    stack.push(i);
  }

  sortedIndices.sort((a, b) => arr[b] - arr[a] || a - b);
  stack.length = 0;

  for (const i of sortedIndices) {
    while (stack.length && stack[stack.length - 1] < i) {
      evenNext[stack.pop()] = i;
    }
    stack.push(i);
  }

  for (let i = arr.length - 2; i >= 0; i--) {
    if (oddNext[i] !== undefined) {
      oddCanReach[i] = evenCanReach[oddNext[i]];
      if (oddCanReach[i]) result++;
    }
    if (evenNext[i] !== undefined) {
      evenCanReach[i] = oddCanReach[evenNext[i]];
    }
  }

  return result;
};