Hello! Welcome to your next lesson on high-ROI interview patterns.
In our last session, we saw how the basic Last-In, First-Out (LIFO) property of stacks can be used to solve common problems like validating parentheses and evaluating expressions. Today, we're going to level up by exploring a more advanced and powerful application of this data structure: the monotonic stack.
Your goal for this lesson is to learn how to use a monotonic stack to solve 'next greater/smaller element' problems. This specific pattern is a favorite in technical interviews because it requires you to see beyond the brute-force solution and apply a clever optimization that improves time complexity from O(n²) to O(n). Mastering this pattern will add a significant tool to your problem-solving arsenal.
1. What is a Monotonic Stack?
As the name suggests, a monotonic stack is a stack where the elements are always maintained in a specific sorted order, either non-decreasing (increasing) or non-increasing (decreasing) from the bottom to the top of the stack.

There are two types:
- Monotonic Increasing Stack: Each new element pushed is greater than or equal to the element at the top of the stack. This structure is ideal for finding the previous/next smaller element.
- Monotonic Decreasing Stack: Each new element pushed is less than or equal to the element at the top of the stack. This is used for finding the previous/next greater element.
Let's watch a short video that introduces this concept and its purpose.
Monotonic Stack in 6 minutes | LeetCode Pattern
The video 'Monotonic Stack in 6 minutes' by AlgoMasterIO provides a quick and clear definition of what a monotonic stack is and what kinds of problems it helps solve.
Please watch from the beginning until 01:16. Focus on the definitions of monotonic increasing and decreasing stacks and which problem types they correspond to (next/previous greater/smaller).
A key takeaway from the video is the tip to store indices in the stack instead of the actual values. Your background in data structures and algorithms should make it clear why this is beneficial: storing indices gives you access to the original values via the input array while also providing positional information (like distance), which is often required in problem variations.
2. The Core Pattern: Next Greater Element
The canonical problem for this pattern is "Next Greater Element" (NGE).
Problem Statement: Given an array nums, for each element nums[i], find the first element to its right that is strictly greater than nums[i]. If no such element exists, the answer for that position is -1.
Example:
For nums = [2, 1, 5, 6, 2, 3], the next greater elements are [5, 5, 6, -1, 3, -1].

From Brute Force to an O(n) Solution
The straightforward approach is to use nested loops: for each element, you scan the rest of the array to its right. This results in an O(n²) time complexity, which is often too slow for interview constraints.
The key insight for an O(n) solution is this: as we iterate through the array, we can use a stack to keep track of the indices of elements for which we have not yet found a next greater element.
Let's walk through the logic using a monotonically decreasing stack.
The Algorithm
- Initialize an empty
stack(to store indices) and aresultarray of the same size as the input, filled with-1. - Iterate through the input array
numsfrom left to right with indexi. - For each element
nums[i]:- While the
stackis not empty AND the current elementnums[i]is greater than the element at the index on top of the stack (nums[stack[-1]]):- This means
nums[i]is the "next greater element" for the index atstack[-1]. - Pop the index from the stack:
popped_index = stack.pop(). - Update the result:
result[popped_index] = nums[i].
- This means
- After the while loop finishes, push the current index
ionto the stack. The elements on the stack will always correspond to values in decreasing order.
- While the
- After the main loop, any indices remaining in the stack have no next greater element, and their entries in
resultcorrectly remain-1.
To see this algorithm in action, let's turn back to the AlgoMasterIO video.
Monotonic Stack in 6 minutes | LeetCode Pattern
This segment of the video provides a fantastic, step-by-step visualization and code walkthrough for the 'Next Greater Element' problem.
Please watch from 01:16 to 04:40. Pay close attention to how the stack's state changes with each element and how the result array is populated.
For a written explanation and Python implementation, this article is an excellent reference.
The 'Monotonic Stack' article from HelloInterview provides a clear, concise text-based explanation of the 'Next Greater Element' problem.
Read the sections 'Monotonic Stack', 'Problem: Next Greater Element', and 'Processing Next Greater Elements'. This will reinforce the algorithm and show you a clean Python implementation.
Test your understanding!
Trace the state of the stack and result array as you process nums = [4, 5, 2, 10] using the Next Greater Element algorithm.
Show answer
Initial state: stack = [], result = [-1, -1, -1, -1]
-
i = 0,
nums[0] = 4:whileloop condition is false (stack is empty).- Push index 0.
stack = [0].
-
i = 1,
nums[1] = 5:whileloop:stackis not empty.nums[1] > nums[stack[-1]](i.e.,5 > 4) is true.- Pop index 0.
stack = []. result[0] = nums[1] = 5.resultis now[5, -1, -1, -1].
- Pop index 0.
- Push index 1.
stack = [1].
-
i = 2,
nums[2] = 2:whileloop:stackis not empty.nums[2] > nums[stack[-1]](i.e.,2 > 5) is false.- Push index 2.
stack = [1, 2]. (Note:numsat indices [1, 2] are [5, 2], a decreasing sequence).
-
i = 3,
nums[3] = 10:whileloop:stackis not empty.nums[3] > nums[stack[-1]](i.e.,10 > 2) is true.- Pop index 2.
stack = [1]. result[2] = nums[3] = 10.resultis now[5, -1, 10, -1].
- Pop index 2.
whileloop again:stackis not empty.nums[3] > nums[stack[-1]](i.e.,10 > 5) is true.- Pop index 1.
stack = []. result[1] = nums[3] = 10.resultis now[5, 10, 10, -1].
- Pop index 1.
- Push index 3.
stack = [3].
Final result: [5, 10, 10, -1].
3. Common Variations
The beauty of this pattern is its adaptability. By making small tweaks to the logic, you can solve a family of related problems.
-
Next Smaller Element: To find the first element to the right that is smaller, you just flip the condition in the
whileloop:while stack and nums[i] < nums[stack[-1]]. This maintains a monotonically increasing stack. -
Previous Greater/Smaller Element: To find elements to the left, the overall traversal and stack logic remains similar. You still iterate from left to right. However, the meaning of the stack changes slightly. When you are at index
i, the elements on the stack are candidates for being the "previous greater/smaller" element.Let's take Previous Greater Element as an example:
- Iterate
ifrom0ton-1. - While the stack is not empty and
nums[i] >= nums[stack[-1]], pop from the stack. (You are removing elements that are smaller or equal, because they can't be the "previous greater" element fornums[i]). - After the loop, if the stack is not empty, the index at the top is the answer.
result[i] = nums[stack[-1]]. If it's empty,result[i] = -1. - Push
ionto the stack.
- Iterate
The article "Monotonic Stack Problems" provides code templates for all four variations.
Monotonic Stack Problems and How to Solve Them
This article provides a useful set of templates for the four main variations of this pattern: Next Greater, Previous Greater, Next Smaller, and Previous Smaller.
Skim through the sections '1. Next Greater Element', '2. Previous Greater Element', '3. Next Smaller Element', and '4. Previous Smaller Element'. Focus on the Python code snippets to see how the template is modified for each case. Don't worry about deep-diving the explanations, as the core logic is what we've already covered.
4. Application: Daily Temperatures
A common interview question that is a thinly veiled "Next Greater Element" problem is LeetCode 739: Daily Temperatures.
Problem: Given an array of integers temperatures, return an array answer where answer[i] is the number of days you have to wait after the i-th day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0.
This is identical to finding the next greater element, but instead of storing the value, you store the distance between the indices (next_greater_index - current_index).
Let's see the solution to this problem, which directly applies the pattern we just learned.
Monotonic Stack in 6 minutes | LeetCode Pattern
The final segment of the 'Monotonic Stack in 6 minutes' video applies the pattern to the 'Daily Temperatures' problem.
Watch from 04:40 to the end. Observe how the core NGE algorithm is adapted to calculate the difference in indices instead of the value itself.
Conclusion
You have now learned a powerful and efficient pattern for a class of problems that frequently appear in technical interviews. Moving from a brute-force O(n²) solution to an optimized O(n) solution using a monotonic stack demonstrates a deep understanding of both algorithms and data structures.
Key Takeaways:
- A monotonic stack maintains its elements in either increasing or decreasing order.
- It is the go-to pattern for finding the next/previous greater/smaller element in an array in linear time, O(n).
- The core mechanism involves iterating through the array and using the stack to hold indices of elements awaiting their "match." When a new element breaks the stack's monotonic property, you've found the answer for the elements you pop.
- Storing indices on the stack is more flexible than storing values, as it allows for calculating distances or retrieving original values.
In our next lesson, we will introduce the deque (double-ended queue) and use it to solve another high-ROI pattern: the sliding window maximum. This will continue our journey of applying linear data structures to solve complex problems efficiently.