07. Next Greater Element in Circular Array

βœ… GFG solution to the Next Greater Element in Circular Array problem: find the next greater element for each element in a 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.

Circular Property:

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 solution leverages a Monotonic Stack combined with a Circular Traversal to efficiently compute the Next Greater Element for each position in the array:

Monotonic Stack with Circular Traversal

  1. Problem Observation:

    • We're asked to find the next greater element for every element in the array, considering the array as circular.

    • If no greater element exists, return -1 for that position.

  2. Circular Traversal Strategy:

    • To simulate a circular array, we traverse the array twice (from 2n-1 to 0), using modulo (% n) to wrap around.

    • This ensures every element can β€œsee” all others to its right and left (as per circular property).

  3. Stack Stores Candidates:

    • Use a monotonic decreasing stack to keep track of potential "next greater" elements.

    • Elements in the stack are always greater than the current value for which we are finding the NGE.

  4. Processing Each Index (Right to Left):

    • For every index i from 2n-1 to 0:

      • Discard all elements from the stack that are less than or equal to arr[i % n] (they can't be NGE).

      • If we're in the first pass (i < n):

        • The top of the stack is the next greater element for this index.

        • If the stack is empty, it means no NGE exists; keep result as -1.

      • Push arr[i % n] into the stack for future comparisons.

  5. Result Accumulation:

    • Maintain a res[] array initialized to -1.

    • Update the result during the first pass only, to avoid overwriting values from the second simulated pass.

πŸ“ 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 during the 2*n traversal.

  • Expected Auxiliary Space Complexity: O(n), for the stack that stores at most n elements in the worst case.

πŸ§‘β€πŸ’» Code (C++)

⚑ View Alternative Approaches with Code and Analysis

πŸ“Š 2️⃣ Single Pass with Index Stack

πŸ’‘ Algorithm Steps:

  1. Use stack to store indices instead of values

  2. Single traversal with circular array simulation

  3. Direct result assignment during traversal

  4. Efficient memory usage

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n)

  • Auxiliary Space: πŸ’Ύ O(n) - for stack

βœ… Why This Approach?

  • Forward traversal with index tracking

  • Direct result assignment

  • Better cache locality

πŸ“Š 3️⃣ Optimized Value Stack

πŸ’‘ Algorithm Steps:

  1. Traverse array twice for circular behavior

  2. Use value-based stack operations

  3. Minimize stack operations

  4. Early termination optimizations

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n)

  • Auxiliary Space: πŸ’Ύ O(n) - for stack with pairs

βœ… Why This Approach?

  • Combined value and index tracking

  • Efficient pair operations

  • Reduced lookup overhead

πŸ“Š 4️⃣ Reverse Traversal Optimization

πŸ’‘ Algorithm Steps:

  1. Reverse order traversal for efficiency

  2. Maintain monotonic decreasing stack

  3. Immediate result assignment

  4. Optimal for sorted arrays

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n)

  • Auxiliary Space: πŸ’Ύ O(n) - for stack

βœ… Why This Approach?

  • Efficient reverse processing

  • Minimal conditional checks

  • Optimal for decreasing sequences

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

πŸ” Circular Array + Monotonic Stack

🟒 O(n)

🟑 O(n)

πŸš€ Simple implementation

πŸ’Ύ Reverse traversal overhead

πŸ”Ί Index Stack Forward

🟒 O(n)

🟑 O(n)

πŸ”§ Direct assignment

πŸ’Ύ Index management overhead

⏰ Pair Stack Forward

🟒 O(n)

🟑 O(n)

πŸš€ Combined tracking

πŸ”„ Pair creation overhead

πŸ“Š Optimized Reverse

🟒 O(n)

🟑 O(n)

⚑ Minimal conditionals

πŸ”§ Less intuitive flow

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

⚑ General purpose

πŸ₯‡ Circular Array + Monotonic Stack

β˜…β˜…β˜…β˜…β˜…

πŸ“Š Memory constrained

πŸ₯ˆ Optimized Reverse

β˜…β˜…β˜…β˜…β˜†

🎯 Forward processing preference

πŸ₯‰ Index Stack Forward

β˜…β˜…β˜…β˜…β˜†

πŸš€ Competitive programming

πŸ… Value Stack Reverse

β˜…β˜…β˜…β˜…β˜…

πŸ§‘β€πŸ’» 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

Visitor counter

Last updated