intermediate8 min read·Updated September 21, 2026

Next Greater Element Explained: Tracing [2, 1, 2, 4, 3] with a Stack

Master the monotonic stack pattern by walking through the exact state changes for [2, 1, 2, 4, 3]. Build your mental model for $O(n)$ time search.

By Learnisim AI·Published September 21, 2026
LEARNING ARCSetup → Model in the example → Full trace → Twist → Edge cases → Apply
PREREQUISITES
  • Basic array manipulation
  • Stack push and pop operations
  • Big-O time complexity
Next Greater Element via Monotonic Stack: [2, 1, 2, 4, 3] 1. Input Array & Final Result i=0 i=1 i=2 i=3 i=4 2 1 2 4 3 Result: [4, 2, 4, -1, -1] 4 2 4 -1 -1 2. Monotonic Decreasing Stack (Indices) Stores indices; values decrease from bottom to top Index 3 (val: 4) TOP Index 4 (val: 3) (Bottom) Key Invariant Rules: • Incoming > Stack Top? Pop & resolve result! • Incoming ≤ Stack Top? Push & wait. • Guarantees O(n) linear time complexity. • Eliminates redundant trailing scans entirely. 3. Step-by-Step Trace Breakdown Step 1: i=0 (2) Stack empty Push index 0 [0] Step 2: i=1 (1) 1 not > 2 (top) Push index 1 [0,1] Step 3: i=2 (2) 2 > 1 → Pop i=1 res[1]=2, Push i=2 Step 4 & 5: Processing 4 and 3 • i=3 (val 4): pops index 0 (val 2) & index 2 (val 2), setting res[0]=4, res[2]=4. • i=4 (val 3): no larger element ahead; remaining stack indices keep default -1.
Next greater of [2, 1, 2, 4, 3] overview diagram
Why

Why Searching for the Next Greater Element Gets Brutally Slow

Phase 1: The Brute-Force Wall

Imagine you are handed the array nums = [2, 1, 2, 4, 3]. Your task is simple to state: for every element, find the very first number to its right that is strictly greater than it. If no such number exists, report -1 for that position. For our array, running through this check gives the expected result [4, 2, 4, -1, -1].
How would you solve this if you started writing code right now? The most intuitive approach is to stand at each element, look to the right one step at a time, and stop the moment you find a larger value. For the first element 2, you scan 1, then 2, then 4, and spot 4 as the winner. Then you move to index 1 (value 1) and scan right until you hit 2.
This nested scanning works fine for five elements. But what happens when the array grows to 100,000 elements, or worse, has a long descending trend where every element has to scan all the way to the end? Your computer ends up performing redundant work, repeatedly looking at the same trailing numbers over and over again. We need a way to look forward without scanning the entire remaining tail from scratch for every single index.
python
def next_greater_naive(nums):
    # Try writing a nested loop for nums = [2, 1, 2, 4, 3]
    pass
Why Searching for the Next Greater Element Gets Brutally Slow Input Array: [ 2, 1, 2, 4, 3 ] → Expected Result: [ 4, 2, 4, -1, -1 ] Phase 1: The Brute-Force Wall (Nested Scanning) 2 idx 0 1 idx 1 2 idx 2 4 idx 3 3 idx 4 The Redundancy Problem O(N²): • Stand at index 0 (val 2), scan right step-by-step until 4. • Move to index 1 (val 1), rescan elements already checked! • With 100,000 elements or long descents, this re-scans the same trailing tail over and over. Extremely slow. Phase 2: The Monotonic Stack Solution O(N) — Smart Deferred Resolution 1. Single Pass Left-to-Right • Iterate through array once. • Push unresolved elements onto a decreasing stack. Never rescan completed tails. 2. Resolve on Greater Found • When current item > stack top, pop the stack and record the current item as next greater. O(1) amortized per element. 3. Final Output Result Array: [ 4, 2, 4, -1, -1 ] Time: O(N) | Space: O(N)
Why Searching for the Next Greater Element Gets Brutally Slow diagram
Model

The Monotonic Stack Mental Model for Linear Search

Phase 2: The Monotonic Stack Model

When we look at our working example nums = [2, 1, 2, 4, 3], finding each element's next greater value naively means scanning ahead repeatedly, taking time. To crush this into , we need a data structure that remembers past elements and automatically discards them the moment their next greater value walks in. Enter the monotonic decreasing stack.
Imagine the stack not as a generic list, but as a waiting room for elements whose next greater value has not yet been found. We push indices (or values) onto this stack such that the values inside are always strictly decreasing from bottom to top. Why decreasing? Because any incoming number that is larger than the element at the top of the stack has finally found its answer.
For nums = [2, 1, 2, 4, 3], when our scanner encounters the second 2, it is larger than the 1 currently sitting at the top of our stack. The 1 can now be resolved: its next greater element is 2. We pop 1, record its answer, and check the next stack element. This LIFO (Last-In, First-Out) structure lets each element peek at the future without re-scanning the array from scratch.
Monotonic Decreasing Stack: Next Greater Element O(n) Working Example: nums = [2, 1, 2, 4, 3] → Result = [4, 2, 4, -1, -1] 1. Linear Scan Array i:0 2 i:1 1 i:2 (curr) 2 i:3 4 i:4 3 2. Monotonic Decreasing Stack (Waiting Room) Stores indices where values are strictly decreasing (bottom → top) TOP OF STACK BOTTOM OF STACK Index 2 (val: 2) Active incoming Index 1 (val: 1) Popped! Next greater = 2 Index 0 (val: 2) Waiting for larger (Empty Stack Slot) 3. The Resolution Rule (Why Monotonic?) Incoming 2 > Stack Top 1 We found the next greater element for index 1! POP Index 1 & Record Result Result[1] = 2. Stack maintains strictly decreasing order. O(n) Time Complexity Guarantee Every element is pushed and popped at most once. Scans & triggers pop Triggers resolution Key Takeaway: Stack eliminates nested loops by instantly resolving past elements when a larger value appears.
The Monotonic Stack Mental Model for Linear Search diagram
Worked example

Tracing the Monotonic Stack Step-by-Step on [2, 1, 2, 4, 3]

Phase 3: Worked Example

To see how the monotonic stack eliminates redundant scanning, let us trace our locked example: . We want an output array of the same length, initialized to , and a stack that stores indices rather than raw values. Storing indices lets us update the result array directly when we find a greater element.

Given

- Input array:
- Initial stack: [] (stores indices)
- Result array:

Steps

1. Index 0 (Value 2):
- Stack is empty. We push index 0.
- Stack (indices): [0] (representing values [2]).
2. Index 1 (Value 1):
- Compare nums[1] (1) with (which is ). Since , no pop occurs.
- Push index 1.
- Stack (indices): [0, 1] (representing values [2, 1]).
3. Index 2 (Value 2):
- Compare nums[2] (2) with stack top (1). , so we pop index 1!
- Set .
- Next, compare (2) with the new stack top (2). , so we stop popping.
- Push index 2.
- Stack (indices): [0, 2] (representing values [2, 2]).
- Current : [-1, 2, -1, -1, -1].
4. Index 3 (Value 4):
- Compare nums[3] (4) with stack top (2). , pop index 2, set .
- Compare (4) with stack top (2). , pop index 0, set .
- Stack is now empty. Push index 3.
- Stack (indices): [3] (representing values [4]).
- Current : [4, 2, 4, -1, -1].
5. Index 4 (Value 3):
- Compare nums[4] (3) with stack top (4). , no pop.
- Push index 4.
- Stack (indices): [3, 4] (representing values [4, 3]).

Result

- After the loop finishes, indices 3 and 4 remain in the stack because no strictly greater element appeared to their right. Their result values correctly remain -1.
- Final result array: .
Try this: Trace the stack and result array when the algorithm reaches index 3 (Value 4) in nums = [2, 1, 2, 4, 3]. Which indices are popped from the stack during this single iteration?
Phase 3 Worked Example: Tracing nums = [2, 1, 2, 4, 3] Highlighting Step 4: Index 3 (Value 4) Triggers Pops & Updates Result Input Array (nums) i:0 2 i:1 1 i:2 2 i:3 (curr) 4 i:4 3 Result Array (res) — Updated at indices 0 & 2 res[0] 4 res[1] 2 res[2] 4 res[3] -1 res[4] -1 Monotonic Stack (Indices) Top → Index 3 (Val: 4) No elements > 4 below Stack is now empty before push Stores indices so res[] is updated instantly Decreasing order of values maintained Popped During Step 4 (Val: 4) Popped Index 2 (Val: 2) 4 > 2 → Set res[2] = 4 Popped Index 0 (Val: 2) 4 > 2 → Set res[0] = 4 Key Insight at Index 3 1. New element `4` is larger than stack tops `2` and `2`. 2. Both are popped & their next greater is found (4). Eliminates O(N²) nested loops!
Tracing the Monotonic Stack Step-by-Step on [2, 1, 2, 4, 3] diagram
Practice

Practice Monotonic Stack Stack Traces on a Modified Array

Phase 4: Practice

Now it is time to put your monotonic stack tracking skills into practice. Recall how the stack stores indices, popping elements whenever a newly scanned value is strictly greater than the element at the top of the stack.
Consider a slightly modified version of our working example array: nums = [3, 1, 4, 2, 5]. Your task is to mentally trace the stack operations from left to right and predict the resulting next greater element array.
Remember the invariant established in our earlier trace: every time you pop an index from the stack, the current element being scanned is its next greater value. Elements left in the stack at the end of the pass receive -1.
python
nums = [3, 1, 4, 2, 5]
# What is the resulting next greater element array?
# result = [...]
Apply

Applying the Monotonic Stack Pattern to Circular Arrays

Phase 5: Transfer

Having mastered the monotonic stack on our locked array [2, 1, 2, 4, 3], you can now port this exact pattern to more complex variations, such as circular arrays where the search wraps around from the end to the beginning.
In a standard linear array, elements at the end like 3 in our locked example defaulted to -1 because no elements sat to their right. But what if the array wraps around like a clock face? You can simulate a circular array without duplicating the memory by running your monotonic stack loop for iterations, using the modulo operator i % N to index into the array.
Just as we popped elements when a larger value arrived in our original trace, elements near the end of the array can now wrap around to find their next greater element among the values sitting at the front. The stack logic remains completely identical—storing indices and resolving pending values—proving that the monotonic stack is a versatile template for range-bound search problems far beyond simple linear scans.
python
def nextGreaterElementsCircular(nums):
    # Apply the 2N index trick with i % len(nums)
    pass

FAQ

What is the next greater element for the value 4 in the array [2, 1, 2, 4, 3]?
The next greater element for 4 is -1 because there are no elements to its right that are strictly greater than 4.
Why use a monotonic stack instead of nested loops?
Nested loops take time by repeatedly scanning ahead. A monotonic stack keeps elements in sorted order, allowing each element to be pushed and popped at most once, reducing time complexity to .
What does 'monotonic decreasing' mean in this context?
A monotonic decreasing stack stores elements from bottom to top in descending order. When a larger element is encountered, it triggers pops for all smaller elements waiting for their next greater match.
What is the time and space complexity of the monotonic stack approach?
Both time and space complexity are in the worst case, as every element is pushed and popped from the stack at most once, and the stack can hold up to elements.

Keep learning