Stacks & Queues · 9 of 38
Find the next Greater element
For every kid in a line, find the first taller kid standing to their right.
- Simple way
- time O(n^2)
room O(1) - Clever way
- time O(n)
room O(n)
The problem, simply
You get an array of numbers. For each number, find the first number to its right that is bigger. If there is none, write -1.
Give back an array of answers, one per position.
A story to remember it
Picture it
For 3, the first bigger number to the right is 5. For 7, we skip 3, 5, 4 and 6 and land on 8. The last number, 8, has nothing to its right, so its answer is -1.
- looking now
- checking
- answer
Examples
A normal case
- In
[4, 5, 2, 25]- Out
[5, 25, 25, -1]
4 sees 5 right away. 5 and 2 both find 25. Nothing is to the right of 25, so -1.
A dip in the middle
- In
[13, 7, 6, 12]- Out
[-1, 12, 12, -1]
Nothing to the right of 13 is bigger. Both 7 and 6 are beaten by 12.
Going down
- In
[5, 4, 3, 2]- Out
[-1, -1, -1, -1]
Each number is smaller than the one before, so no one ever finds a bigger number.
All the same
- In
[2, 2, 2]- Out
[-1, -1, -1]
Equal is not bigger. This is the case where using < instead of <= gives the wrong answer.
Way 1: the simple way
For each position, look to the right one by one until you find a bigger number.
- For each
i, startjati + 1. - Move
jright untilarr[j] > arr[i], and writearr[j]. - If
jruns off the end, write-1.
Way 1 for 7 at index 1: j checks 3, 5, 4 and 6 before finding 8. Many numbers are checked again and again for different i.
- looking now
- checking
- answer
class Solution {
public int[] nextGreater(int[] arr) {
int n = arr.length;
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
ans[i] = -1;
for (int j = i + 1; j < n; j++) {
if (arr[j] > arr[i]) { // first bigger one wins
ans[i] = arr[j];
break;
}
}
}
return ans;
}
}How long it takes: for a falling array like [5, 4, 3, 2], every i scans to the end, so about n * n / 2 checks, O(n^2). Extra room: O(1) besides the answer.
Way 2: the clever way
Walk from right to left and keep a pile of "kids who could still block someone", a stack. The pile is always in order: bigger at the bottom, smaller on top.
- Start at the last index with an empty stack.
- For
arr[i], pop every value on top that is less than or equal toarr[i]. They are hidden behindarr[i]and can never be anyone's answer again. - Now the top, if any, is the first bigger number to the right. Write it, or
-1if the stack is empty. - Push
arr[i], since it may block someone further left.
Each number is pushed once and popped at most once, so the whole walk is fast.
Right to left with a stack of possible blockers
01 / 10
Start just past the right end with an empty stack. The answer row is blank.
- looking now
- done
- answer
- rejected
- just added
class Solution {
public int[] nextGreater(int[] arr) {
int n = arr.length;
int[] ans = new int[n];
Deque<Integer> stack = new ArrayDeque<>(); // possible blockers
for (int i = n - 1; i >= 0; i--) {
while (!stack.isEmpty() && stack.peek() <= arr[i]) {
stack.pop(); // hidden behind arr[i]
}
ans[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(arr[i]);
}
return ans;
}
}How long it takes: each number goes onto the stack once and comes off at most once, so the total work is O(n), even though there is a loop inside a loop. Extra room: the stack can hold all n numbers when the array is falling, O(n).
Watch out for
- Some versions want the index of the next greater element, not its value. Push indices onto the stack and compare
arr[stack.peek()]. - The left to right version also works: keep indices of numbers still waiting for an answer, and when a bigger number comes, pop them and fill their answers. Both are
O(n). - The nested
whilemakes people sayO(n^2). Explain the "pushed once, popped once" argument out loud.
What interviewers ask next
- Circular array, where the search wraps around to the start. Walk
ifrom2n - 1down to0and usearr[i % n]. The first pass fills the stack with what lies "after the end". - Next smaller element. Same code, flip the comparison: pop values greater than or equal to
arr[i]. - Daily temperatures: how many days until a warmer day? Store indices, and the answer is
j - i. - Next greater element for a list of query numbers (LeetCode 496). Run this once on the big array, save answers in a hash map, then look each query up.
- Stock span and largest rectangle in a histogram use the same stack that keeps its values in order.
Remember this
Grown-up words: the group of possible blockers is a monotonic stack (its values only go one way, here decreasing from bottom to top), the first taller kid is the next greater element, and "pushed once, popped once" is amortized analysis.