Next Greater Element medium
Description
Given an array nums, for each element find the next greater element to its right — the first element after it that is strictly larger. If no such element exists, return -1 for that position.
Examples
> Case 1:
Input: nums = [4, 5, 2, 25]
Output: [5, 25, 25, -1]
nums[0]=4 → next greater is 5
nums[1]=5 → next greater is 25
nums[2]=2 → next greater is 25
nums[3]=25 → no element greater after it → -1
> Case 2:
Input: nums = [13, 7, 6, 12]
Output: [-1, 12, 12, -1]Constraints
1 <= nums.length <= 10^4- Solve in O(n) time, not O(n²).
Intuition
The brute force is “for each element, scan to the right until we find something larger.” That’s O(n²).
The key observation: once we know that some earlier element hasn’t found its next-greater yet, we don’t need to look at it again until we see a larger value. We can park “still waiting” elements on a stack, in decreasing order, and pop them off as we discover their answer.
This pattern is called a monotonic stack — we maintain the invariant that the stack is sorted (here, decreasing from bottom to top).
Algorithm
Walk the array left to right. For each nums[i]:
- While the stack is non-empty and
nums[i]is greater than the top, the top element has just found its next greater (nums[i]). Pop it and record the answer. - Push the current index onto the stack.
When the loop ends, anything still on the stack has no next greater — answer is -1 for those.
nums = [4, 5, 2, 25]
i=0 nums[0]=4 stack empty → push 0 stack=[0] ans=[?, ?, ?, ?]
i=1 nums[1]=5 5 > nums[0]=4 → pop 0, ans[0]=5
push 1 stack=[1] ans=[5, ?, ?, ?]
i=2 nums[2]=2 2 < nums[1]=5 → don't pop
push 2 stack=[1,2] ans=[5, ?, ?, ?]
i=3 nums[3]=25 25 > nums[2]=2 → pop 2, ans[2]=25
25 > nums[1]=5 → pop 1, ans[1]=25
stack empty → push 3 stack=[3] ans=[5, 25, 25, ?]
End. Stack=[3] still has 3 → ans[3]=-1.
Final: [5, 25, 25, -1] ✓Code
Why this is O(n)
It looks like a nested loop, but every index is pushed onto the stack once and popped at most once. Total work is at most 2n operations across the entire run — that’s O(n) amortized, even though any single iteration might do a lot of popping.
The pattern: whenever a problem says “for each element, find the nearest something to its left/right,” reach for a monotonic stack. Variants include “previous smaller,” “next smaller,” “daily temperatures,” “largest rectangle in histogram,” and “trapping rain water.”
Analysis
- Time:
O(n)— each index enters and leaves the stack at most once. - Space:
O(n)— stack can hold all indices in the worst case (strictly decreasing input).