Next Greater Element II
Given a circular integer array nums (i.e., the next element of nums[nums.length - 1] is nums[0]), return the next greater number for every element in nums. The next greater number of a number x is the first greater number to its traversing-order next in the array, which means you could search circularly to find its next greater number. If it doesn't exist, return -1.
- 1 <= nums.length <= 10⁴
- -10⁹ <= nums[i] <= 10⁹
nums = [1,2,1][2,-1,2]nums = [5,4,3,2,1][-1,5,5,5,5]Before diving into this circular version, it is highly recommended to first understand the linear Next Greater Element I logic, where we use a Monotonic Stack as a Waiting Room for numbers.
Standard search ends at the last index. But in a Circular Array, the end of the line wraps back to the beginning. If an element near the end hasn't found its "Next Greater" neighbor yet, it deserves a second chance to look at the numbers at the start of the array.
Think of it as a Circular Marathon. Every runner (number) gets two laps to find someone faster than them. If they still haven't found anyone after two laps, they are officially the fastest in their circle.
Instead of physically doubling the array (which wastes memory), we mentally simulate two laps using the Modulo Operator (%).
1. The Setup: We run a loop from 0 to 2*N - 1.
2. The Modulo Trick: We use "i % N" to find the real index in the original array. This allows us to treat the sequence [1, 2, 3] as [1, 2, 3, 1, 2, 3] seamlessly.
3. The Rules:
- Resolving: Every element we see acts as a "challenger" to those in the stack. We pop and resolve them exactly like in the linear version.
- Pushing: We ONLY push elements into the stack during the First Lap (i < N). During the second lap, everyone has already had their chance to be a waiter; they are only there to resolve the stragglers left over from the first lap.
stack = []
results = [-1] * N
// Run for two laps (2 * N)
FOR i from 0 to (2 * N) - 1:
current_val = nums[i % N]
// Standard Monotonic Resolution
WHILE stack is NOT empty AND current_val > nums[stack.PEEK()]:
resolved_index = stack.POP()
results[resolved_index] = current_val
// Only push during the first lap
IF i < N:
stack.PUSH(i)
RETURN resultsNext Greater Element II Strategy
Mental Model
- Circular Illusion: Iterate `2N` times with `% N` to wrap indices back.
- Doubling Search: Pass 1 fills the stack with pending candidates; Pass 2 checks if start elements can satisfy them.
Virtual Doubling
You don't need to copy the array. Just iterate `2 * N` times and use `i % N` to wrap indices back to the start. The logic is identical to the linear version!