If a problem is suitable to use the monotonic stack, it must have at least three characters:
- It is a “range queries in an array” problem.
- The minima/maxima element or the monotonic order of elements in a range is useful to get the answer to every range query.
- When an element is popped from the monotonic stack, it will never be used again.
Solution for leetcode 739
https://leetcode.com/problems/daily-temperatures/
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
Stack<Integer> stack = new Stack();
int[] output = new int[n];
for(int i = n - 1; i >= 0; i--){
while(!stack.isEmpty() && temperatures[stack.peek()] <= temperatures[i]){
stack.pop();
}
if(stack.isEmpty()){
output[i] = 0;
}
else{
output[i] = stack.peek() - i;
}
stack.add(i);
}
return output;
}
}
Thoughts on leetcode 84
https://leetcode.com/problems/largest-rectangle-in-histogram/
For a height at index i, if we can find its left and right boundaries, we can find its area. By maintaining a monotonic stack, we can find the left and right boundaries when we pop elements from the stack. (it's very important to understand the characteristics)
Solution for leetcode 84
https://leetcode.com/problems/largest-rectangle-in-histogram/
class Solution {
public int largestRectangleArea(int[] heights) {
Stack<Integer> stack = new Stack();
int maxArea = Integer.MIN_VALUE;
//calculate the area when iterating through the heights array
for(int i = 0; i < heights.length; i++){
while(!stack.isEmpty() && heights[stack.peek()] > heights[i]){
int height = heights[stack.pop()];
int left = stack.isEmpty()? -1 : stack.peek();
int width = i - left - 1;
int area = height * width;
maxArea = area > maxArea ? area : maxArea;
}
stack.add(i);
}
//calculate the remaining area when poping the element from the stack
//the right boundary of the remaining elements in the stack is the end
while(!stack.isEmpty()){
int height = heights[stack.pop()];
int left = stack.isEmpty()? -1 : stack.peek();
int right = heights.length;
int width = right - left - 1;
int area = height * width;
maxArea = area > maxArea ? area : maxArea;
}
return maxArea;
}
}
Thoughts on leetcode 42
https://leetcode.com/problems/trapping-rain-water/
Solution for leetcode 42
class Solution {
public int trap(int[] height) {
Stack<Integer> stack = new Stack();
int rain = 0;
for(int i = 0; i < height.length; i++){
while(!stack.isEmpty() && height[stack.peek()] <= height[i]){
int low = height[stack.pop()];
if(!stack.isEmpty()){
int prev = height[stack.peek()];
int tall = Math.min(prev, height[i]) - low;
int width = i - stack.peek() -1;
rain += tall * width;
}
}
stack.add(i);
}
return rain;
}
}
Solution for leetcode 901
https://leetcode.com/problems/online-stock-span/
class StockSpanner {
Stack<Integer> stack;
ArrayList<Integer> arr;
int cur = -1;
public StockSpanner() {
stack = new Stack();
arr = new ArrayList();
}
public int next(int price) {
if(stack.isEmpty() || arr.get(stack.peek()) > price){
cur++;
stack.add(cur);
arr.add(price);
return 1;
}
else{
while(!stack.isEmpty() && arr.get(stack.peek()) <= price){
stack.pop();
}
cur++;
int prev = stack.isEmpty()? -1 : stack.peek();
int output = cur - prev;
stack.add(cur);
arr.add(price);
return output;
}
}
}