Odd Even Jump (Hard)

AbhiAbhi
6 min read

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.

Example 1:

Input: arr = [10,13,12,14,15]
Output: 2
Explanation: 
From starting index i = 0, we can make our 1st jump to i = 2 (since arr[2] is the smallest among arr[1], arr[2], arr[3], arr[4] that is greater or equal to arr[0]), then we cannot jump any more.
From starting index i = 1 and i = 2, we can make our 1st jump to i = 3, then we cannot jump any more.
From starting index i = 3, we can make our 1st jump to i = 4, so we have reached the end.
From starting index i = 4, we have reached the end already.
In total, there are 2 different starting indices i = 3 and i = 4, where we can reach the end with some number of
jumps.

Example 2:

Input: arr = [2,3,1,1,4]
Output: 3
Explanation: 
From starting index i = 0, we make jumps to i = 1, i = 2, i = 3:
During our 1st jump (odd-numbered), we first jump to i = 1 because arr[1] is the smallest value in [arr[1], arr[2], arr[3], arr[4]] that is greater than or equal to arr[0].
During our 2nd jump (even-numbered), we jump from i = 1 to i = 2 because arr[2] is the largest value in [arr[2], arr[3], arr[4]] that is less than or equal to arr[1]. arr[3] is also the largest value, but 2 is a smaller index, so we can only jump to i = 2 and not i = 3
During our 3rd jump (odd-numbered), we jump from i = 2 to i = 3 because arr[3] is the smallest value in [arr[3], arr[4]] that is greater than or equal to arr[2].
We can't jump from i = 3 to i = 4, so the starting index i = 0 is not good.
In a similar manner, we can deduce that:
From starting index i = 1, we jump to i = 4, so we reach the end.
From starting index i = 2, we jump to i = 3, and then we can't jump anymore.
From starting index i = 3, we jump to i = 4, so we reach the end.
From starting index i = 4, we are already at the end.
In total, there are 3 different starting indices i = 1, i = 3, and i = 4, where we can reach the end with some
number of jumps.

Example 3:

Input: arr = [5,1,3,4,2]
Output: 3
Explanation: We can reach the end from starting indices 1, 2, and 4.

Let’s solve the challenging and elegant "Odd Even Jump" problem using your structured, interview-friendly approach β€” with clear logic and optimized code 🧠πŸ’ͺ


βœ… 1. Problem Explanation (In Simple Terms)

You're given an array arr of integers.

You start at any index i and want to reach the end of the array by jumping.

Jump Rules:

  • You alternate between odd and even jumps.

  • On the odd jump:

    • You must jump to the smallest index j > i such that arr[j] β‰₯ arr[i]
  • On the even jump:

    • You must jump to the smallest index j > i such that arr[j] ≀ arr[i]

You win if you can reach the last index.

❓ Return the total number of starting indices i where you can reach the end by obeying the odd-even rules.


πŸ’‘ 2. Key Insights

  1. It's a DP problem from the end of the array backwards:

    • We track: "can we reach the end from i with an odd jump?" and "with an even jump?"
  2. At each position:

    • Precompute the next index for an odd jump

    • Precompute the next index for an even jump

  3. Use monotonic stacks and TreeMap-style sorting to efficiently compute jump destinations.


🧠 3. Steps to Solve

  1. Initialize n = arr.length

  2. Create two arrays:

    • odd[i] = can we reach end from i starting with odd jump?

    • even[i] = can we reach end from i starting with even jump?

  3. For last index n-1 β†’ both odd[n-1] = even[n-1] = true

  4. Precompute:

    • nextHigher[i] = index to jump to on an odd jump

    • nextLower[i] = index to jump to on an even jump

  5. Process backwards:

    • If nextHigher[i] is defined β†’ odd[i] = even[nextHigher[i]]

    • If nextLower[i] is defined β†’ even[i] = odd[nextLower[i]]

  6. Count how many odd[i] == true β†’ those are valid starting points


βœ… 4. JavaScript Code (Optimized & Clean)

/**
 * @param {number[]} arr
 * @return {number}
 */
function oddEvenJumps(arr) {
  const n = arr.length;

  // Step 1: Helper to build jump maps
  const makeJumpMap = (compareFn) => {
    const result = Array(n).fill(-1);
    const stack = [];
    const indices = Array.from({ length: n }, (_, i) => i)
      .sort((a, b) => arr[a] - arr[b] || a - b); // sort indices by value, then index

    if (compareFn === 'desc') indices.sort((a, b) => arr[b] - arr[a] || a - b);

    for (const i of indices) {
      while (stack.length && i > stack[stack.length - 1]) {
        result[stack.pop()] = i;
      }
      stack.push(i);
    }

    return result;
  };

  // Step 2: Precompute jump destinations
  const nextHigher = makeJumpMap('asc');
  const nextLower = makeJumpMap('desc');

  // Step 3: DP arrays
  const odd = Array(n).fill(false);
  const even = Array(n).fill(false);
  odd[n - 1] = even[n - 1] = true;

  // Step 4: Fill DP bottom-up
  for (let i = n - 2; i >= 0; i--) {
    if (nextHigher[i] !== -1) {
      odd[i] = even[nextHigher[i]];
    }
    if (nextLower[i] !== -1) {
      even[i] = odd[nextLower[i]];
    }
  }

  // Step 5: Count how many odd[i] are true
  return odd.filter(Boolean).length;
}

πŸ” 5. Dry Run Example

Input: [10, 13, 12, 14, 15]

β†’ From 0 (10):
   - Odd jump β†’ 2 (12) β†’ even β†’ 3 (14) β†’ odd β†’ 4 (15) βœ…

β†’ From 1 (13):
   - Odd β†’ 3 (14) β†’ even β†’ 4 βœ…

β†’ From 2 (12):
   - Odd β†’ 3 (14) β†’ even β†’ 4 βœ…

β†’ From 3 (14):
   - Odd β†’ 4 βœ…

β†’ From 4: already at end βœ…

βœ… Total = 5

⏱️ 6. Time & Space Complexity

  • Sorting each jump list: O(n log n)

  • Stack processing: O(n)

  • DP fill: O(n)

βœ… Total Time: O(n log n)
βœ… Space: O(n)


βœ… Final Verdict

  • A beautiful mix of:

    • Preprocessing with monotonic stacks

    • DP to track jump reachability

  • Commonly asked in top-tier interviews (Google, Amazon, etc.)

  • Excellent to show off sorting, DP, and stack skills

0
Subscribe to my newsletter

Read articles from Abhi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abhi
Abhi