from bisect import bisect_left, bisect_right
def oddEvenJumps(arr):
n = len(arr)
odd = [False] * n
even = [False] * n
odd[-1] = even[-1] = True
# Pair value with index and sort for odd jumps (smallest >= arr[i])
idxs = sorted(range(n), key=lambda i: (arr[i], i))
next_higher = [None] * n
stack = []
for i in idxs:
while stack and i > stack[-1]:
next_higher[stack.pop()] = i
stack.append(i)
# Pair value with index and sort for even jumps (largest <= arr[i])
idxs = sorted(range(n), key=lambda i: (-arr[i], i))
next_lower = [None] * n
stack = []
for i in idxs:
while stack and i > stack[-1]:
next_lower[stack.pop()] = i
stack.append(i)
for i in range(n - 2, -1, -1):
if next_higher[i] is not None:
odd[i] = even[next_higher[i]]
if next_lower[i] is not None:
even[i] = odd[next_lower[i]]
return sum(odd)
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;
class Solution {
public:
int oddEvenJumps(vector<int>& arr) {
int n = arr.size();
vector<bool> odd(n, false), even(n, false);
odd[n-1] = even[n-1] = true;
vector<int> next_higher(n, -1), next_lower(n, -1);
// Next higher
vector<int> idxs(n);
for (int i = 0; i < n; ++i) idxs[i] = i;
sort(idxs.begin(), idxs.end(), [&arr](int i, int j) {
return arr[i] == arr[j] ? i < j : arr[i] < arr[j];
});
stack<int> st;
for (int i : idxs) {
while (!st.empty() && i > st.top()) {
next_higher[st.top()] = i;
st.pop();
}
st.push(i);
}
// Next lower
sort(idxs.begin(), idxs.end(), [&arr](int i, int j) {
return arr[i] == arr[j] ? i < j : arr[i] > arr[j];
});
while (!st.empty()) st.pop();
for (int i : idxs) {
while (!st.empty() && i > st.top()) {
next_lower[st.top()] = i;
st.pop();
}
st.push(i);
}
for (int i = n-2; i >= 0; --i) {
if (next_higher[i] != -1)
odd[i] = even[next_higher[i]];
if (next_lower[i] != -1)
even[i] = odd[next_lower[i]];
}
int res = 0;
for (bool b : odd) if (b) ++res;
return res;
}
};
import java.util.*;
class Solution {
public int oddEvenJumps(int[] arr) {
int n = arr.length;
boolean[] odd = new boolean[n];
boolean[] even = new boolean[n];
odd[n-1] = even[n-1] = true;
int[] nextHigher = new int[n];
int[] nextLower = new int[n];
Integer[] idxs = new Integer[n];
for (int i = 0; i < n; i++) idxs[i] = i;
Arrays.sort(idxs, (a, b) -> arr[a] != arr[b] ? Integer.compare(arr[a], arr[b]) : Integer.compare(a, b));
Stack<Integer> stack = new Stack<>();
Arrays.fill(nextHigher, -1);
for (int i : idxs) {
while (!stack.isEmpty() && i > stack.peek()) {
nextHigher[stack.pop()] = i;
}
stack.push(i);
}
Arrays.sort(idxs, (a, b) -> arr[a] != arr[b] ? Integer.compare(arr[b], arr[a]) : Integer.compare(a, b));
Arrays.fill(nextLower, -1);
stack.clear();
for (int i : idxs) {
while (!stack.isEmpty() && i > stack.peek()) {
nextLower[stack.pop()] = i;
}
stack.push(i);
}
for (int i = n - 2; i >= 0; i--) {
if (nextHigher[i] != -1)
odd[i] = even[nextHigher[i]];
if (nextLower[i] != -1)
even[i] = odd[nextLower[i]];
}
int res = 0;
for (boolean b : odd) if (b) res++;
return res;
}
}
var oddEvenJumps = function(arr) {
const n = arr.length;
const odd = new Array(n).fill(false);
const even = new Array(n).fill(false);
odd[n-1] = even[n-1] = true;
function makeNext(sortedIdxs) {
const res = new Array(n).fill(null);
const stack = [];
for (let i of sortedIdxs) {
while (stack.length && i > stack[stack.length-1]) {
res[stack.pop()] = i;
}
stack.push(i);
}
return res;
}
// For odd jumps: sort by value asc, then index asc
let idxs = Array.from({length: n}, (_, i) => i);
idxs.sort((a, b) => arr[a] - arr[b] || a - b);
const nextHigher = makeNext(idxs);
// For even jumps: sort by value desc, then index asc
idxs.sort((a, b) => arr[b] - arr[a] || a - b);
const nextLower = makeNext(idxs);
for (let i = n-2; i >= 0; --i) {
if (nextHigher[i] !== null) odd[i] = even[nextHigher[i]];
if (nextLower[i] !== null) even[i] = odd[nextLower[i]];
}
return odd.filter(Boolean).length;
};
You are given an integer array arr
of length n
. Starting from any index i
, you can make a sequence of jumps to other indices according to the following rules:
j
such that j > i
and arr[j] >= arr[i]
and arr[j]
is as small as possible. If there are multiple such indices, choose the smallest j
.j
such that j > i
and arr[j] <= arr[i]
and arr[j]
is as large as possible. If there are multiple such indices, choose the smallest j
.j
, you stop jumping from that index.
An index is called "good" if starting from it, you can reach the end of the array (index n-1
) by making a sequence of jumps following the rules above.
Your task: Return the total number of "good" starting indices in arr
.
Constraints:
arr.length
<= 2 * 104arr[i]
< 105The problem asks for the number of starting indices from which you can reach the end of the array by alternating between "odd" and "even" jumps, each with their own rules. At first glance, this seems to require simulating all possible jump sequences from each index, which could be very slow for large arrays.
A brute-force approach would be to, for each starting index, simulate all jumps until you either reach the end or get stuck. However, this would result in a time complexity of O(n2) or worse, which is not feasible for large inputs.
To optimize, we need to precompute, for each index, where the next "odd" and "even" jump would land. Once we have this information, we can use dynamic programming to determine if a given index can reach the end via valid jumps, by working backwards from the end of the array.
The key insight is that the "next jump" for each index depends only on the array structure, and we can use sorting and a stack to efficiently compute these next jumps for all indices.
Let's break down the solution step by step:
i
, find the next index j
you would jump to on an odd jump (smallest j > i
with arr[j] >= arr[i]
, and arr[j]
is as small as possible).
i
, find the next index j
for an even jump (smallest j > i
with arr[j] <= arr[i]
, and arr[j]
is as large as possible).
arr[i]
(ascending for odd, descending for even) and use a stack to process indices in order, assigning "next jump" pointers.
odd
and even
, where odd[i]
is true if you can reach the end from i
using an odd jump first, and even[i]
is true if you can reach the end from i
using an even jump first.
odd
and even
using the precomputed next jumps:
i
is j
, then odd[i] = even[j]
.
i
is j
, then even[i] = odd[j]
.
odd[i]
is true, since we always start with an odd jump.The use of sorting and stacks allows us to precompute the next jumps efficiently, and the dynamic programming step ensures we only process each index once.
Let's walk through an example with arr = [10, 13, 12, 14, 15]
:
odd[4] = even[4] = True
.
odd[3] = even[4] = True
; even jump (no valid index), so even[3] = False
.
odd[2] = even[3] = False
; even jump to 3, so even[2] = odd[3] = True
.
odd[1] = even[3] = False
; even jump to 2, so even[1] = odd[2] = False
.
odd[0] = even[1] = False
; even jump (no valid index), so even[0] = False
.
odd[i] = True
are 3 and 4. So the answer is 2.
This process efficiently computes which indices are "good" by working backwards and using precomputed jump targets.
The Odd Even Jump problem challenges us to find efficient ways to simulate a sequence of jumps through an array under alternating rules. By precomputing the next valid jumps using sorting and stacks, and leveraging dynamic programming to propagate reachability from the end of the array backwards, we achieve an efficient O(n log n) solution. The approach is elegant because it decouples the jump-finding logic from the reachability logic, and uses well-known algorithms (sorting, stack-based processing, and DP) in a creative way to solve a complex problem.