18. Next Greater Element in Circular Array
β GFG solution to the Next Greater Element in Circular Array problem: find next greater element for each position in circular array using monotonic stack technique. π
The problem can be found at the following link: π Question Link
π§© Problem Description
Given a circular integer array arr[], the task is to determine the next greater element (NGE) for each element in the array.
The next greater element of an element arr[i] is the first element that is greater than arr[i] when traversing circularly. If no such element exists, return -1 for that position.
Note: Since the array is circular, after reaching the last element, the search continues from the beginning until we have looked at all elements once.
π Examples
Example 1
Input: arr[] = [1, 3, 2, 4]
Output: [3, 4, 4, -1]
Explanation:
The next greater element for 1 is 3.
The next greater element for 3 is 4.
The next greater element for 2 is 4.
The next greater element for 4 does not exist, so return -1.Example 2
π Constraints
$1 \le \text{arr.size()} \le 10^5$
$0 \le \text{arr}[i] \le 10^6$
β
My Approach
The optimal approach uses a Monotonic Stack technique with circular array simulation to efficiently find the next greater element:
Monotonic Stack + Circular Traversal
Initialize Variables:
Use a stack to store indices of elements for which we haven't found the next greater element yet.
Create a result vector initialized with -1 for all positions.
Traverse the array twice (2*n iterations) to simulate circular behavior.
Stack Operations:
For each element, pop from stack all indices whose corresponding values are smaller than current element.
Set the next greater element for these popped indices as the current element.
Push current index to stack only in the first traversal (i < n).
Circular Logic:
Use modular arithmetic
i % nto access array elements in circular manner.The second traversal handles cases where next greater element is at the beginning of array.
Monotonic Property:
Stack maintains indices in decreasing order of their corresponding values.
This ensures O(1) amortized time for finding next greater elements.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n), where n is the size of the array. Each element is pushed and popped from the stack at most once, resulting in O(2n) operations which simplifies to O(n).
Expected Auxiliary Space Complexity: O(n), where n is the size of the array. In the worst case (when array is in decreasing order), all indices are stored in the stack simultaneously.
π§βπ» Code (C++)
β‘ View Alternative Approaches with Code and Analysis
π 2οΈβ£ Reverse Traversal with Value Stack
π‘ Algorithm Steps:
Traverse array twice from right to left to simulate circular behavior.
Use stack to store actual values instead of indices for direct comparison.
Pop smaller elements and push current element to maintain decreasing stack.
Stack top gives the next greater element for current position.
π Complexity Analysis:
Time: β±οΈ O(n) - Each element pushed and popped once
Auxiliary Space: πΎ O(n) - Stack space for storing values
β
Why This Approach?
Direct value comparison without index mapping
Intuitive right-to-left processing
Clean stack operations with values
π 3οΈβ£ Two-Pass Index Mapping
π‘ Algorithm Steps:
First pass: Process elements from left and store indices in stack.
Second pass: Continue processing remaining elements in circular manner.
Use index-based stack to track positions and map results efficiently.
Maintain monotonic decreasing stack for optimal performance.
π Complexity Analysis:
Time: β±οΈ O(n) - Two passes through the array
Auxiliary Space: πΎ O(n) - Stack for indices
β
Why This Approach?
Clear separation of circular logic with two explicit passes
Index-based tracking for precise result mapping
Easy to understand and debug
π 4οΈβ£ Optimized Single Loop
π‘ Algorithm Steps:
Single loop with modular arithmetic for circular array simulation.
Process first n elements normally, then continue for circular behavior.
Optimize by avoiding redundant operations in second half.
Use early termination when all results are found.
π Complexity Analysis:
Time: β±οΈ O(n) - Early termination optimization
Auxiliary Space: πΎ O(n) - Stack space
β
Why This Approach?
Early termination when all elements processed
Counter-based optimization for performance
Reduced iterations in best-case scenarios
π π Comparison of Approaches
π Approach
β±οΈ Time Complexity
πΎ Space Complexity
β Pros
β οΈ Cons
π·οΈ Forward Index Stack
π’ O(n)
π’ O(n)
π Clean index mapping
π§ Slightly more complex logic
π Reverse Value Stack
π’ O(n)
π’ O(n)
π Intuitive value comparison
πΎ Stores values instead of indices
π Two-Pass Method
π’ O(n)
π’ O(n)
π― Clear separation of logic
π Always two full passes
π Optimized Single Loop
π’ O(n)
π’ O(n)
β Early termination
π§ Additional counter tracking
π Best Choice Recommendation
π― Scenario
ποΈ Recommended Approach
π₯ Performance Rating
π Interview/Competitive
π₯ Forward Index Stack
β β β β β
π Learning/Understanding
π₯ Reverse Value Stack
β β β β β
π§ Code Clarity
π₯ Two-Pass Method
β β β β β
π― Performance Critical
π Optimized Single Loop
β β β β β
β Code (Java)
π Code (Python)
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated