Next Greater Element in Circular Array in JavaScript

Circular Array

An array in which the next element of the last element is the first element of the array is often termed as circular. This concept allows us to treat arrays as if they wrap around, where after the last index, we continue from the first index.

Obviously, there exists no such mechanism to store data like this. Data will still be stored in continuous memory blocks, and circular arrays are more like a logical concept than physical reality.

Problem

We need to find the next greater element for each element in a circular array. The Next Greater Element is the first element greater than the current element when traversing to the right. If no greater element exists, we return -1.

Since the array is circular, after reaching the end, we continue searching from the beginning.

Example Input and Output

For example, if the input array is:

const arr = [7, 8, 7];

The expected output is:

[8, -1, 8]

Output Explanation

For the first 7 at index 0, the next greater element is 8 at index 1. For 8 at index 1, no greater element exists, so we return -1. For the second 7 at index 2, we continue circularly and find 8 at index 1 as the next greater element.

Algorithm Using Stack

We use a stack-based approach that processes the array twice to handle the circular nature:

const arr = [7, 8, 7];

const nextGreaterElement = (arr = []) => {
    const res = new Array(arr.length).fill(-1);
    const stack = [];
    
    if (!arr || arr.length < 1) {
        return [];
    }
    
    // Process array twice to handle circular nature
    for (let i = 0; i < arr.length * 2; i++) {
        const currentIndex = i % arr.length;
        
        // Pop elements from stack that are smaller than current element
        while (stack.length > 0 && arr[stack[stack.length - 1]] < arr[currentIndex]) {
            const smallerIndex = stack.pop();
            res[smallerIndex] = arr[currentIndex];
        }
        
        // Only push indices in first traversal
        if (i < arr.length) {
            stack.push(currentIndex);
        }
    }
    
    return res;
};

console.log(nextGreaterElement(arr));
[8, -1, 8]

How It Works

The algorithm uses a stack to keep track of indices of elements for which we haven't found the next greater element yet:

  1. Initialize: Create a result array filled with -1 and an empty stack
  2. Double traversal: Process the array twice (2 * length iterations) using modulo to simulate circular behavior
  3. Stack operations: For each element, pop smaller elements from stack and set their next greater element
  4. Push indices: Only push indices during the first traversal to avoid duplicates

Step-by-Step Execution

// Tracing through [7, 8, 7]
const arr = [7, 8, 7];
console.log("Input:", arr);

// Step-by-step execution
let res = [-1, -1, -1];
let stack = [];

console.log("i=0: arr[0]=7, stack=[], push 0");
stack.push(0);

console.log("i=1: arr[1]=8 > arr[0]=7, pop 0, res[0]=8, push 1");
res[0] = 8;
stack = [1];

console.log("i=2: arr[2]=7 < arr[1]=8, push 2");
stack.push(2);

console.log("i=3: arr[0]=7 < arr[1]=8, no change");
console.log("i=4: arr[1]=8 > arr[2]=7, pop 2, res[2]=8");
res[2] = 8;

console.log("Final result:", res);
Input: [7, 8, 7]
i=0: arr[0]=7, stack=[], push 0
i=1: arr[1]=8 > arr[0]=7, pop 0, res[0]=8, push 1
i=2: arr[2]=7 < arr[1]=8, push 2
i=3: arr[0]=7 < arr[1]=8, no change
i=4: arr[1]=8 > arr[2]=7, pop 2, res[2]=8
Final result: [8, -1, 8]

Testing with Different Arrays

const nextGreaterElement = (arr = []) => {
    const res = new Array(arr.length).fill(-1);
    const stack = [];
    
    if (!arr || arr.length < 1) {
        return [];
    }
    
    for (let i = 0; i < arr.length * 2; i++) {
        const currentIndex = i % arr.length;
        
        while (stack.length > 0 && arr[stack[stack.length - 1]] < arr[currentIndex]) {
            const smallerIndex = stack.pop();
            res[smallerIndex] = arr[currentIndex];
        }
        
        if (i < arr.length) {
            stack.push(currentIndex);
        }
    }
    
    return res;
};

// Test cases
console.log("Test 1:", nextGreaterElement([7, 8, 7]));
console.log("Test 2:", nextGreaterElement([1, 2, 3, 4, 3]));
console.log("Test 3:", nextGreaterElement([5, 4, 3, 2, 1]));
console.log("Test 4:", nextGreaterElement([1]));
Test 1: [8, -1, 8]
Test 2: [2, 3, 4, -1, 4]
Test 3: [-1, -1, -1, -1, -1]
Test 4: [-1]

Time and Space Complexity

Time Complexity: O(n) where n is the length of the array. Each element is pushed and popped at most once.

Space Complexity: O(n) for the stack and result array.

Conclusion

The stack-based approach efficiently finds the next greater element in a circular array by processing the array twice. This technique leverages the circular property while maintaining optimal time complexity.

Updated on: 2026-03-15T23:19:00+05:30

356 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements