Odd Even Jump

hard array dp stack monotonic stack

Problem

Starting from any index, odd-numbered jumps go to the next index with the smallest value ≥ current; even-numbered jumps go to the next index with the largest value ≤ current. Count start positions that reach the last index.

Inputarr = [10,13,12,14,15]
Output2
Precompute oddNext and evenNext via sorted-index stacks; back-fill DP.

def oddEvenJumps(arr):
    n = len(arr)
    def next_arr(idx):
        st = []
        result = [-1] * n
        for i in idx:
            while st and i > st[-1]:
                result[st.pop()] = i
            st.append(i)
        return result
    a = sorted(range(n), key=lambda i: (arr[i], i))
    odd_next = next_arr(a)
    b = sorted(range(n), key=lambda i: (-arr[i], i))
    even_next = next_arr(b)
    odd = [False]*n; even = [False]*n
    odd[-1] = even[-1] = True
    for i in range(n - 2, -1, -1):
        if odd_next[i] != -1: odd[i] = even[odd_next[i]]
        if even_next[i] != -1: even[i] = odd[even_next[i]]
    return sum(odd)
function oddEvenJumps(arr) {
  const n = arr.length;
  function nextArr(idx) {
    const st = []; const res = new Array(n).fill(-1);
    for (const i of idx) {
      while (st.length && i > st[st.length - 1]) res[st.pop()] = i;
      st.push(i);
    }
    return res;
  }
  const a = [...Array(n).keys()].sort((x, y) => arr[x] === arr[y] ? x - y : arr[x] - arr[y]);
  const oddN = nextArr(a);
  const b = [...Array(n).keys()].sort((x, y) => arr[x] === arr[y] ? x - y : arr[y] - arr[x]);
  const evenN = nextArr(b);
  const odd = new Array(n).fill(false), even = new Array(n).fill(false);
  odd[n - 1] = even[n - 1] = true;
  for (let i = n - 2; i >= 0; i--) {
    if (oddN[i] !== -1) odd[i] = even[oddN[i]];
    if (evenN[i] !== -1) even[i] = odd[evenN[i]];
  }
  return odd.filter(Boolean).length;
}
class Solution {
    public int oddEvenJumps(int[] arr) {
        int n = arr.length;
        Integer[] aIdx = new Integer[n], bIdx = new Integer[n];
        for (int i = 0; i < n; i++) { aIdx[i] = i; bIdx[i] = i; }
        Arrays.sort(aIdx, (x, y) -> arr[x] == arr[y] ? x - y : arr[x] - arr[y]);
        Arrays.sort(bIdx, (x, y) -> arr[x] == arr[y] ? x - y : arr[y] - arr[x]);
        int[] oddN = nextArr(aIdx, n), evenN = nextArr(bIdx, n);
        boolean[] odd = new boolean[n], even = new boolean[n];
        odd[n - 1] = even[n - 1] = true;
        int count = 1;
        for (int i = n - 2; i >= 0; i--) {
            if (oddN[i] != -1) odd[i] = even[oddN[i]];
            if (evenN[i] != -1) even[i] = odd[evenN[i]];
            if (odd[i]) count++;
        }
        return count;
    }
    int[] nextArr(Integer[] idx, int n) {
        int[] res = new int[n]; Arrays.fill(res, -1);
        Deque<Integer> st = new ArrayDeque<>();
        for (int i : idx) {
            while (!st.isEmpty() && i > st.peek()) res[st.pop()] = i;
            st.push(i);
        }
        return res;
    }
}
int oddEvenJumps(vector<int>& arr) {
    int n = (int)arr.size();
    auto nextArr = [&](vector<int>& idx) {
        vector<int> res(n, -1); stack<int> st;
        for (int i : idx) {
            while (!st.empty() && i > st.top()) { res[st.top()] = i; st.pop(); }
            st.push(i);
        }
        return res;
    };
    vector<int> aIdx(n), bIdx(n);
    iota(aIdx.begin(), aIdx.end(), 0); iota(bIdx.begin(), bIdx.end(), 0);
    sort(aIdx.begin(), aIdx.end(), [&](int x, int y){ return arr[x] == arr[y] ? x < y : arr[x] < arr[y]; });
    sort(bIdx.begin(), bIdx.end(), [&](int x, int y){ return arr[x] == arr[y] ? x < y : arr[x] > arr[y]; });
    auto oddN = nextArr(aIdx), evenN = nextArr(bIdx);
    vector<bool> odd(n, false), even(n, false);
    odd[n - 1] = even[n - 1] = true; int count = 1;
    for (int i = n - 2; i >= 0; i--) {
        if (oddN[i] != -1) odd[i] = even[oddN[i]];
        if (evenN[i] != -1) even[i] = odd[evenN[i]];
        if (odd[i]) count++;
    }
    return count;
}
Time: O(n log n) Space: O(n)