In competitive programming and technical interviews, the Monotonic Stack is one of the most powerful patterns used to solve array-based problems with time constraints. Let’s break it down and see how it can be a game-changer in your algorithm arsenal.


🔍 What is a Monotonic Stack?

A Monotonic Stack is a stack that is maintained in either increasing or decreasing order. It is not a data structure on its own, but a technique used to solve problems related to:

  • Next Greater / Smaller Element
  • Previous Greater / Smaller Element
  • Stock Span
  • Trapping Rain Water
  • Largest Rectangle in Histogram
  • Daily Temperatures

🧭 Types of Monotonic Stacks

Stack Type Maintains Used For
Increasing Increasing order (bottom → top) Next Smaller Element
Decreasing Decreasing order (bottom → top) Next Greater Element

🧠 Core Idea

  • Push values while maintaining order.
  • Pop from the stack if the current element breaks the order.
  • Helps find nearest elements (to the left or right) efficiently.

📘 Example 1: Next Greater Element

🔧 Problem:

Given an array, for each element, find the next greater element to its right.

public int[] nextGreaterElement(int[] nums) {
    int n = nums.length;
    int[] result = new int[n];
    Stack<Integer> stack = new Stack<>();

    for (int i = n - 1; i >= 0; i--) {
        while (!stack.isEmpty() && stack.peek() <= nums[i]) {
            stack.pop();
        }
        result[i] = stack.isEmpty() ? -1 : stack.peek();
        stack.push(nums[i]);
    }
    return result;
}

Time Complexity: O(n)


📘 Example 2: Previous Smaller Element

🔧 Problem:

Find the nearest smaller element to the left for every element.

public int[] previousSmallerElement(int[] nums) {
    int[] result = new int[nums.length];
    Stack<Integer> stack = new Stack<>();

    for (int i = 0; i < nums.length; i++) {
        while (!stack.isEmpty() && stack.peek() >= nums[i]) {
            stack.pop();
        }
        result[i] = stack.isEmpty() ? -1 : stack.peek();
        stack.push(nums[i]);
    }
    return result;
}

📘 Example 3: Largest Rectangle in Histogram

🔧 Problem:

Given the heights of bars in a histogram, find the largest rectangular area.

public int largestRectangleArea(int[] heights) {
    Stack<Integer> stack = new Stack<>();
    int maxArea = 0;
    int n = heights.length;

    for (int i = 0; i <= n; i++) {
        int h = (i == n) ? 0 : heights[i];
        while (!stack.isEmpty() && h < heights[stack.peek()]) {
            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;
}

📌 Concept: This uses both next and previous smaller concepts in a single pass.


📘 Example 4: Trapping Rain Water

🔧 Problem:

Given an elevation map, compute how much water can be trapped.

public int trap(int[] height) {
    Stack<Integer> stack = new Stack<>();
    int water = 0, i = 0;

    while (i < height.length) {
        while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
            int top = stack.pop();
            if (stack.isEmpty()) break;

            int distance = i - stack.peek() - 1;
            int boundedHeight = Math.min(height[i], height[stack.peek()]) - height[top];
            water += distance * boundedHeight;
        }
        stack.push(i++);
    }
    return water;
}

📘 Example 5: Daily Temperatures

🔧 Problem:

Return an array where res[i] = days until a warmer temperature.

public int[] dailyTemperatures(int[] temperatures) {
    int[] result = new int[temperatures.length];
    Stack<Integer> stack = new Stack<>();

    for (int i = 0; i < temperatures.length; i++) {
        while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
            int prev = stack.pop();
            result[prev] = i - prev;
        }
        stack.push(i);
    }
    return result;
}

💡 Key Takeaways

  • Use increasing or decreasing stacks based on the problem.
  • Monotonic stacks help you reduce time complexity from O(n²) to O(n).
  • Commonly used in sliding window, range-based, and histogram problems.

🎯 Final Tip

Always ask:

  • Do I need the next/previous greater/smaller element?
  • Do I need it to the left or to the right?

If yes → 💡 Monotonic Stack is your friend!