Monotonic stack helps find next/previous greater or smaller elements in linear time. It avoids repeated backward or forward scans.
Core Idea
Store indices in a stack with monotonic order of values.
- decreasing stack -> next greater queries
- increasing stack -> next smaller queries
Each index is pushed and popped at most once.
Template: Next Greater Element (Right)
public int[] nextGreaterRight(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
Arrays.fill(ans, -1);
Deque<Integer> st = new ArrayDeque<>(); // stores indices
for (int i = 0; i < n; i++) {
while (!st.isEmpty() && nums[i] > nums[st.peek()]) {
ans[st.pop()] = nums[i];
}
st.push(i);
}
return ans;
}
Problem 1: Daily Temperatures
public int[] dailyTemperatures(int[] t) {
int n = t.length;
int[] ans = new int[n];
Deque<Integer> st = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!st.isEmpty() && t[i] > t[st.peek()]) {
int j = st.pop();
ans[j] = i - j;
}
st.push(i);
}
return ans;
}
Problem 2: Next Greater Element II (Circular)
public int[] nextGreaterElements(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
Arrays.fill(ans, -1);
Deque<Integer> st = new ArrayDeque<>();
for (int i = 0; i < 2 * n; i++) {
int idx = i % n;
while (!st.isEmpty() && nums[idx] > nums[st.peek()]) {
ans[st.pop()] = nums[idx];
}
if (i < n) st.push(idx);
}
return ans;
}
Problem 3: Largest Rectangle in Histogram
public int largestRectangleArea(int[] h) {
int n = h.length, best = 0;
Deque<Integer> st = new ArrayDeque<>();
for (int i = 0; i <= n; i++) {
int curr = (i == n) ? 0 : h[i];
while (!st.isEmpty() && curr < h[st.peek()]) {
int height = h[st.pop()];
int left = st.isEmpty() ? -1 : st.peek();
int width = i - left - 1;
best = Math.max(best, height * width);
}
st.push(i);
}
return best;
}
Common Mistakes
- Storing values instead of indices when distance is required
- Choosing wrong monotonic direction
- Forgetting final flush pass
- Handling duplicates inconsistently (
<vs<=)
Duplicate Tie-Breaking Rule
For contribution-count problems (like subarray minimums), duplicate handling must be asymmetric:
- one side uses strict comparison (
<) - other side uses non-strict (
<=)
Without this, equal values may be double-counted or under-counted.
Document your tie rule before coding.
Debug Template
During development, log stack indices and values:
i=5 val=7 stack=[4(6),2(3)] -> pop 4, answer[4]=7
If results are wrong, inspect:
- whether pops occur at correct comparator condition
- whether unresolved indices are handled in final flush
Most monotonic stack bugs are comparator or flush mistakes.
Practice Set (Recommended Order)
- Next Greater Element I (LC 496)
LeetCode - Daily Temperatures (LC 739)
LeetCode - Next Greater Element II (LC 503)
LeetCode - Largest Rectangle in Histogram (LC 84)
LeetCode - Maximal Rectangle (LC 85)
LeetCode - Sum of Subarray Minimums (LC 907)
LeetCode
Key Takeaways
- Monotonic stacks solve neighbor/range-boundary queries in
O(n). - Index storage is usually required for width/distance calculations.
- The push-pop invariant is the core correctness argument.
Comments