This problem asks for the minimum cost to reach the last index of an array, given constraints on valid jumps and costs associated with each index. The solution uses a combination of a monotonic stack and dynamic programming.
1. Monotonic Stack for Finding Valid Jumps:
The core idea is to efficiently identify all valid jumps from a given index. The constraints specify that a jump from i
to j
is valid only if the sequence of numbers between i
and j
is either strictly decreasing (if nums[i] > nums[j]
) or strictly increasing (if nums[i] <= nums[j]
).
We use two monotonic stacks:
nums
values. When processing an index i
, we pop elements from the stack as long as their nums
values are less than nums[i]
. The last popped element (if any) represents the farthest index with a smaller nums
value that's reachable from i
—a valid jump according to the problem constraints.nums
values. It finds the farthest reachable index with a larger (or equal) nums
value.These stacks efficiently identify valid jump targets for each index in O(n) time, avoiding nested loops.
2. Adjacency List (Graph Representation):
After using the monotonic stacks, we construct an adjacency list to represent the graph of possible jumps. g[i]
stores the indices that can be jumped to from index i
.
3. Dynamic Programming for Minimum Cost:
Finally, dynamic programming is used to find the minimum cost. f[i]
represents the minimum cost to reach index i
.
f[0] = 0
(starting at index 0 with zero cost). Other f[i]
values are initialized to infinity.i
, we examine each j
in g[i]
(each valid jump from i
). We update f[j]
using the formula: f[j] = min(f[j], f[i] + costs[j])
. This means the cost to reach j
is the minimum between its current cost and the cost to reach i
plus the cost to jump to j
.f[n - 1]
contains the minimum cost to reach the last index.Time Complexity: O(n) - The monotonic stacks and the dynamic programming iteration each take linear time.
Space Complexity: O(n) - To store the adjacency list g
and the DP array f
.
Code Example (Python):
from collections import defaultdict
import math
class Solution:
def minCost(self, nums: List[int], costs: List[int]) -> int:
n = len(nums)
g = defaultdict(list)
# Decreasing stack
stk = []
for i in range(n - 1, -1, -1):
while stk and nums[stk[-1]] < nums[i]:
stk.pop()
if stk:
g[i].append(stk[-1])
stk.append(i)
# Increasing stack
stk = []
for i in range(n - 1, -1, -1):
while stk and nums[stk[-1]] >= nums[i]:
stk.pop()
if stk:
g[i].append(stk[-1])
stk.append(i)
f = [math.inf] * n # Initialize DP array
f[0] = 0
for i in range(n):
for j in g[i]:
f[j] = min(f[j], f[i] + costs[j])
return f[n - 1]
The code in other languages (Java, C++, Go, TypeScript) follows the same logic, with appropriate adjustments for syntax and data structures. The key is the efficient use of monotonic stacks for jump identification and the subsequent dynamic programming for cost minimization.