Next greater element in a Circular Array
Given a circular array arr[], find the next greater element for each element in the array.
Note: The next greater element of an element is the first next element greater than it when traversing the array in order (circularly). If no such element exists, return -1 for that position.
Examples:
Input: arr[] = [5, 7, 1, 2, 6]
Output: [7, -1, 2, 6, 7]
Explanation:
Next greater element for 5 is 7.
For 7, no greater element exists, so it is -1.
For 1, the next greater element is 2.
For 2, the next greater element is 6.
For 6, the next greater element is 7 (circularly).Input: arr[] = [6, 8, 0, 1, 3]
Output: [8, -1, 1, 3, 6]
Explanation: In the array, the next larger element to 6 is 8, for 8 there is no larger elements hence it is -1, for 0 it is 1, for 1 it is 3 and then for 3 there is 6.
Table of Content
[Naive Approach] - Using Nested Loops - O(n^2) Time and O(1) Space
In a circular array, after reaching the n-th index, traversal continues again from index 0. To handle this, we can use the modulo operator. By iterating from index i to i + n and accessing elements as index % n, we can simulate circular traversal within the array itself. This allows us to process the circular nature of the array without using any extra space.
#include <iostream>
#include <vector>
using namespace std;
vector<int> nextGreater(vector<int> &arr) {
int n = arr.size();
vector<int> res(n, -1);
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
// Checking for next greater element
if (arr[i] < arr[(i + j)%n]) {
res[i] = arr[(i + j)%n];
break;
}
}
}
return res;
}
int main() {
vector<int> arr = {5, 7, 1, 2, 6};
vector<int> ans = nextGreater(arr);
for(auto i:ans) {
cout<<i<<" ";
}
return 0;
}
import java.util.ArrayList;
class GfG {
static ArrayList<Integer> nextGreater(int[] arr) {
int n = arr.length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = -1;
}
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
// Checking for next greater element
if (arr[i] < arr[(i + j) % n]) {
res[i] = arr[(i + j) % n];
break;
}
}
}
ArrayList<Integer> result = new ArrayList<>();
for (int val : res) {
result.add(val);
}
return result;
}
public static void main(String[] args) {
int[] arr = {5, 7, 1, 2, 6};
ArrayList<Integer> ans = nextGreater(arr);
for (int i : ans) {
System.out.print(i + " ");
}
}
}
def nextGreater(arr):
n = len(arr)
res = [-1] * n
for i in range(n):
for j in range(1, n):
# Checking for next greater element
if arr[i] < arr[(i + j) % n]:
res[i] = arr[(i + j) % n]
break
return res
if __name__ == "__main__":
arr = [5, 7, 1, 2, 6]
ans = nextGreater(arr)
for i in ans:
print(i, end=" ")
using System;
using System.Collections.Generic;
class GfG {
static List<int> nextGreater(int[] arr) {
int n = arr.Length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = -1;
}
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
// Checking for next greater element
if (arr[i] < arr[(i + j) % n]) {
res[i] = arr[(i + j) % n];
break;
}
}
}
List<int> result = new List<int>();
foreach (int val in res) {
result.Add(val);
}
return result;
}
static void Main() {
int[] arr = { 5, 7, 1, 2, 6};
List<int> ans = nextGreater(arr);
foreach (int i in ans) {
Console.Write(i + " ");
}
}
}
function nextGreater(arr) {
let n = arr.length;
let res = new Array(n).fill(-1);
for (let i = 0; i < n; i++) {
for (let j = 1; j < n; j++) {
// Checking for next greater element
if (arr[i] < arr[(i + j) % n]) {
res[i] = arr[(i + j) % n];
break;
}
}
}
return res;
}
// Driver Code
let arr = [5, 7, 1, 2, 6];
let ans = nextGreater(arr);
for (let i of ans) {
process.stdout.write(i + " ");
}
Output
7 -1 2 6 7
[Expected Approach] Using Stack - O(n) Time and O(n) Space
We use the same ideas as next greater element in a normal array. Stack to find out the next greater element in linear time. We traverse the array from right to left. For each element, we remove elements from the stack that are smaller than or equal to it, as they cannot be the next greater element. If the stack is not empty after this, the top element of the stack is the next greater element for the current element. We then push the current element onto the stack.
Step By Step Implementations:
- Initialize res with -1 and an empty stack st.
- Loop from 2n - 1 to 0 to handle circular traversal.
- Use i%n to access the correct index in the array.
- While stack is not empty and top element is ≤ current element, pop from stack.
- If i < n and stack is not empty, set res[i] to st.top().
- Push current element arr[i % n] to the stack.
- Return the result array res.
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
vector<int> nextGreater(vector<int> &arr) {
int n = arr.size();
vector<int> res(n, -1);
stack<int> st;
// Traverse the array from right to left
for (int i = 2 * n - 1; i >= 0; i--) {
// Pop elements from the stack that are less
// than or equal to the current element
while (!st.empty() && st.top() <= arr[i % n]) {
st.pop();
}
// If the stack is not empty, the top element
// is the next greater element
if (i < n && !st.empty()) {
res[i] = st.top();
}
st.push(arr[i % n]);
}
return res;
}
int main() {
vector<int> arr = {5, 7, 1, 2, 6};
vector<int> res = nextGreater(arr);
for (int x : res) {
cout << x << " ";
}
return 0;
}
import java.util.ArrayList;
import java.util.Stack;
class GfG {
static ArrayList<Integer> nextGreater(int[] arr) {
int n = arr.length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = -1;
}
Stack<Integer> st = new Stack<>();
for (int i = 2 * n - 1; i >= 0; i--) {
int curr = arr[i % n];
// Pop elements smaller
// than or equal to current
while (!st.isEmpty() && st.peek() <= curr) {
st.pop();
}
// Assign next greater
// if within first pass
if (i < n && !st.isEmpty()) {
res[i] = st.peek();
}
st.push(curr);
}
ArrayList<Integer> result = new ArrayList<>();
for (int val : res) {
result.add(val);
}
return result;
}
public static void main(String[] args) {
int[] arr = {5, 7, 1, 2, 6};
ArrayList<Integer> ans = nextGreater(arr);
for (int x : ans) {
System.out.print(x + " ");
}
}
}
def nextGreater(arr):
n = len(arr)
res = [-1] * n
st = []
for i in range(2 * n - 1, -1, -1):
# Pop elements from the stack that are less
# than or equal to the current element
while st and st[-1] <= arr[i % n]:
st.pop()
# If the stack is not empty, the top element
# is the next greater element
if i < n and st:
res[i] = st[-1]
st.append(arr[i % n])
return res
if __name__ == "__main__":
arr = [5, 7, 1, 2, 6]
ans = nextGreater(arr)
for x in ans:
print(x, end=" ")
using System;
using System.Collections.Generic;
class GfG {
static List<int> nextGreater(int[] arr) {
int n = arr.Length;
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = -1;
}
Stack<int> st = new Stack<int>();
for (int i = 2 * n - 1; i >= 0; i--) {
int curr = arr[i % n];
while (st.Count > 0 && st.Peek() <= curr) {
st.Pop();
}
if (i < n && st.Count > 0) {
res[i] = st.Peek();
}
st.Push(curr);
}
List<int> result = new List<int>();
foreach (int val in res) {
result.Add(val);
}
return result;
}
static void Main() {
int[] arr = {5, 7, 1, 2, 6};
List<int> ans = nextGreater(arr);
foreach (int x in ans) {
Console.Write(x + " ");
}
}
}
function nextGreater(arr) {
let n = arr.length;
let res = new Array(n).fill(-1);
let st = [];
for (let i = 2 * n - 1; i >= 0; i--) {
// Pop elements from the stack that are less
// than or equal to the current element
while (st.length > 0 &&
st[st.length - 1] <= arr[i % n]) {
st.pop();
}
// If the stack is not empty, the top element
// is the next greater element
if (i < n && st.length > 0) {
res[i] = st[st.length - 1];
}
// Push the current element onto the stack
st.push(arr[i % n]);
}
return res;
}
// Driver Code
let arr = [5, 7, 1, 2, 6];
let ans = nextGreater(arr);
for (let x of ans) {
process.stdout.write(x + " ");
}
Output
7 -1 2 6 7