Maintain increasing/decreasing stacks to find next/previous greater or smaller elements efficiently
Push indices/heights while maintaining monotonicity; pop when invariant breaks to resolve answers spanning the popped element.
Use for next greater/smaller queries, histogram rectangles, stock span, or removing digits for minimal number.
Pop while current breaks monotonic property to discover next boundary
def next_greater(nums):
res, stack = [-1] * len(nums), [] # stack of indices
for i, v in enumerate(nums):
while stack and nums[stack[-1]] < v:
res[stack.pop()] = v
stack.append(i)
return res
Use increasing stack of heights; compute area when a lower bar appears
def largest_rectangle(heights):
st = [] # (index)
max_area = 0
for i, h in enumerate(heights + [0]):
while st and heights[st[-1]] > h:
height = heights[st.pop()]
left = st[-1] + 1 if st else 0
width = i - left
max_area = max(max_area, height * width)
st.append(i)
return max_area
Monotonic stack of decreasing prices to compute span
class StockSpanner:
def __init__(self):
self.st = [] # (price, span)
def next(self, price: int) -> int:
span = 1
while self.st and self.st[-1][0] <= price:
span += self.st.pop()[1]
self.st.append((price, span))
return span
def template(*args, **kwargs):
# General template placeholder
pass
Each element is pushed and popped at most once.
Stack may hold indices in worst case.