Monotonic Stack Pattern Java
Fast recall
Quick revision
Core answer
Whether you know the pop-while-violation invariant and the amortized O(n) analysis
Not seeing why it's O(n) (each element pushed/popped once), or storing values when indices are needed
Explain the amortized O(n) (each index in/out once) and store indices for distance-based answers
Interview-ready guide
Interview answer
A monotonic stack is a stack whose elements are kept in a consistent order, either always increasing or always decreasing.
I maintain that order by popping any element that would violate it before I push the new element. And the clever part is that the moment I pop something is exactly when I've discovered a relationship, like the next greater element.
The reason this pattern is so valuable is that it solves next-greater, next-smaller, previous-greater, and previous-smaller element problems in O of n total time, whereas the brute force of comparing each element against all the others is O of n squared.
The key to seeing why it's linear is the amortized analysis: each element is pushed onto the stack exactly once and popped at most once, so even though there's a nested while loop, the total number of pushes and pops across the whole run is bounded by two n, which is O of n.
A concrete example is the daily temperatures problem, where for each day I want to know how many days until a warmer temperature. I use a stack of indices with decreasing temperatures.
For each new day, while the current temperature is warmer than the temperature at the index on top of the stack, I pop that index, and the current day is its next warmer day, so I record the distance as the difference in indices. Then I push the current index.
A couple of tips: I store indices rather than values whenever the answer involves a distance or width, and I pick the stack direction based on the question, decreasing for next-greater, increasing for next-smaller. Indices left on the stack at the end simply have no greater element.
Monotonic Stack Pattern Java
Direct Answer
A monotonic stack keeps its elements in sorted order (always increasing or always decreasing) by popping any element that would break the order before pushing. It solves next/previous greater (or smaller) element problems in O(n) total - each element is pushed and popped at most once - instead of the O(n^2) brute force. Classic uses: daily temperatures, stock span, largest rectangle in histogram.
Deep Dive & Architecture
A monotonic stack stores unresolved candidates in increasing or decreasing order. When a new value breaks that order, it answers the question for one or more stored candidates before they are removed.
Worked example: daily temperatures [73, 74, 75, 71, 69, 72, 76, 73]
Store indexes whose warmer day is not known yet. Temperature 74 is warmer than 73, so pop index 0 and record a wait of 1 day. Temperature 75 resolves index 1. Values 71 and 69 remain stacked; when 72 arrives, it resolves 69 after 1 day and 71 after 2 days. Later 76 resolves 72, 75, and any smaller unresolved values.
Indexes are stored instead of only temperatures because the answer needs a distance. The stack is decreasing by temperature from bottom to top; every item on it is still waiting for a greater value to its right.
Although one new value may trigger several pops, each index is pushed once and popped at most once. Total time is therefore O(n), not O(n²), and space is O(n). Changing the comparison changes the problem: a decreasing stack finds next-greater values, while an increasing stack can find next-smaller values. Decide whether equal values should pop based on whether the question asks for strictly greater or greater-or-equal.
Code Example
int[] dailyTemperatures(int[] t) {
int[] ans = new int[t.length];
Deque<Integer> stack = new ArrayDeque<>(); // indices, decreasing temps
for (int i = 0; i < t.length; i++) {
while (!stack.isEmpty() && t[i] > t[stack.peek()]) {
int j = stack.pop(); // i is the next warmer day for j
ans[j] = i - j; // distance in days
}
stack.push(i);
}
return ans; // leftover indices stay 0
}
// t = {73,74,75,71,69,72,76,73}
// ans = {1,1,4,2,1,1,0,0} - each index pushed/popped once -> O(n)
Common Mistakes & Pitfalls
- Thinking it's O(n^2): the nested while is amortized O(n) - each index enters/leaves once.
- Storing values not indices: distance-based answers (days, widths) need indices.
- Wrong monotonic direction: next-greater uses a decreasing stack; next-smaller uses increasing.
- Forgetting leftovers: indices still on the stack have no greater/smaller element (answer 0 / -1).
Check your understanding
Answer these without looking back at the article.
- What is a stack and what are its core operations?
- What is a queue and how does it differ from a stack?
- How do you check for balanced parentheses using a stack?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.