Monotonic Stack Introduction
Monotonic Stack Introduction
A monotonic stack is a stack that maintains elements in either strictly increasing or strictly decreasing order.
Types
- Monotonic Decreasing: Top is smallest element
- Monotonic Increasing: Top is largest element
Why It Works
When we encounter an element that violates the monotonic property, we pop elements and process them. Each element is pushed and popped at most once.
Time Complexity
O(n) - each element is pushed and popped at most once.
When to Use
- Next greater element
- Next smaller element
- Largest rectangle in histogram
- Daily temperatures
- Stock span problem
Monotonic Stack Problems
Monotonic Stack Problems
1. Next Greater Element (LeetCode 496)
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
Map<Integer, Integer> map = new HashMap<>();
Deque<Integer> stack = new ArrayDeque<>();
for (int num : nums2) {
while (!stack.isEmpty() && stack.peek() < num) {
map.put(stack.pop(), num);
}
stack.push(num);
}
int[] result = new int[nums1.length];
for (int i = 0; i < nums1.length; i++) {
result[i] = map.getOrDefault(nums1[i], -1);
}
return result;
}
// Time: O(n), Space: O(n)
2. Daily Temperatures (LeetCode 739)
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
int[] result = new int[n];
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && temperatures[stack.peek()] < temperatures[i]) {
int prevIndex = stack.pop();
result[prevIndex] = i - prevIndex;
}
stack.push(i);
}
return result;
}
// Time: O(n), Space: O(n)
3. Largest Rectangle in Histogram (LeetCode 84)
public int largestRectangleArea(int[] heights) {
Deque<Integer> stack = new ArrayDeque<>();
int maxArea = 0;
int n = heights.length;
for (int i = 0; i <= n; i++) {
int currentHeight = (i == n) ? 0 : heights[i];
while (!stack.isEmpty() && heights[stack.peek()] > currentHeight) {
int height = heights[stack.pop()];
int width = stack.isEmpty() ? i : i - stack.peek() - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
}
Template
// Next Greater Element (Decreasing Stack)
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && arr[stack.peek()] < arr[i]) {
int index = stack.pop();
result[index] = i; // or arr[i]
}
stack.push(i);
}
// Next Smaller Element (Increasing Stack)
for (int i = 0; i < n; i++) {
while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
int index = stack.pop();
result[index] = i; // or arr[i]
}
stack.push(i);
}
Practice Problems
Given an array of temperatures, return an array answer where answer[i] is the number of days you have to wait to get a warmer temperature.
Example:
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]
Wait 1 day for 74, 4 days for 76, etc.
Edge Cases:
- All same temperature — all answers are 0
- Strictly decreasing — all answers are 0 except last
- Strictly increasing — answers are [1,1,...,1,0]
- Single element — answer is [0]
- Two elements, second warmer — answer is [1,0]
Given a circular integer array nums, return the next greater number for every element.
Example:
Input: nums = [1,2,1]
Output: [2,-1,2]
Circular array: next greater of last element is 2.
Edge Cases:
- All elements same — all answers are -1
- Strictly increasing — each answer is the next element, last is -1
- Strictly decreasing — all answers are -1 except last wraps to first
- Single element — answer is [-1]
- Two elements, second larger — [nums[1], -1]
Design a StockSpanner class that calculates the span of stock prices. The span is the maximum number of consecutive days for which the price was less than or equal to today's price.
Example:
Input: StockSpanner s = new StockSpanner(); s.next(100); s.next(80); s.next(60); s.next(70); s.next(60); s.next(75); s.next(85);
Output: [1,1,1,2,1,4,6]
Span of 85 is 6 (days 75,60,70,60,80,100 <= 85).
Edge Cases:
- Strictly increasing prices: span grows linearly
- Strictly decreasing prices: all spans are 1
- All same prices: span equals total count
Quiz
1. What is the time complexity of monotonic stack solutions?
2. For next greater element, which stack direction do we use?
3. What is a common mistake when implementing Monotonic Stack?
Flashcards
Question
What is a monotonic stack?
Click to reveal answer
Answer
A stack that maintains elements in strictly increasing or decreasing order.
Question
When to use monotonic stack?
Click to reveal answer
Answer
For next greater/smaller element problems, and histogram problems.
Question
Monotonic Stack best practices
Click to reveal answer
Answer
Follow SOLID principles, write clean code, test thoroughly, document decisions, and monitor in production.
Revision Notes
Key Takeaways
- 1. Monotonic stack maintains order
- 2. Each element processed exactly once
- 3. Use for next greater/smaller problems
- 4. Template pattern is reusable
Interview Tips
- • Identify if problem needs next greater/smaller
- • Draw the stack evolution
- • Explain why O(n) is optimal
Cheat Sheet
Monotonic Stack Cheat Sheet
Decreasing Stack: For next greater element
Increasing Stack: For next smaller element
Time: O(n) - each element pushed/popped once
Pattern: Pop while condition violated, push current