1+ from typing import List , Union , Collection , Mapping , Optional
2+
3+
4+ class Solution :
5+ def minCost (self , nums : List [int ], costs : List [int ]) -> int :
6+ """
7+ Example: nums = [3, 1, 2, 4], costs = [1, 2, 3, 4]
8+
9+ From index 0 (value=3):
10+ - Next smaller: index 1 (value=1)
11+ - Next larger: index 3 (value=4)
12+
13+ DP builds cost backwards:
14+ - dp[3] = 0 (at end, no cost)
15+ - dp[2] = dp[3] + costs[3] = 0 + 4 = 4 (can jump to 4)
16+ - dp[1] = dp[2] + costs[2] = 4 + 3 = 7 (can jump to 2)
17+ - dp[0] = min(dp[1]+costs[1], dp[3]+costs[3]) = min(7+2, 0+4) = 4
18+ """
19+
20+ smallStack = [] # Monotonic increasing (next smaller element)
21+ largeStack = [] # Monotonic decreasing (next larger element)
22+ dp = [0 ] * len (nums ) # dp[i] = min cost from i to end
23+
24+ # Process backwards (right to left)
25+ for i in range (len (nums ) - 1 , - 1 , - 1 ):
26+
27+ # Maintain monotonic increasing stack (for next smaller)
28+ # Remove elements >= current (they can't be "next smaller")
29+ while smallStack and nums [smallStack [- 1 ]] >= nums [i ]:
30+ smallStack .pop ()
31+
32+ # Maintain monotonic decreasing stack (for next larger)
33+ # Remove elements < current (they can't be "next larger")
34+ while largeStack and nums [largeStack [- 1 ]] < nums [i ]:
35+ largeStack .pop ()
36+
37+ # Calculate minimum cost for this position
38+ nxtCost = []
39+
40+ if largeStack :
41+ lid = largeStack [- 1 ] # Next larger index
42+ nxtCost .append (dp [lid ] + costs [lid ])
43+
44+ if smallStack :
45+ sid = smallStack [- 1 ] # Next smaller index
46+ nxtCost .append (dp [sid ] + costs [sid ])
47+
48+ # Min cost from current position to end
49+ dp [i ] = min (nxtCost ) if nxtCost else 0
50+
51+ # Add current index to both stacks
52+ largeStack .append (i )
53+ smallStack .append (i )
54+
55+ print (largeStack )
56+ print (smallStack )
57+
58+ print (dp )
59+
60+ return dp [0 ] # Minimum cost from start
0 commit comments