First Greater Element

Last Updated : 15 Jul, 2026

Given an array arr[] of integers, for each element arr[i], find the smallest element arr[j] such that j < i and arr[j] > arr[i]. If no such element exists, return -1 for that position.

Examples:

Input: arr[] = [3, 2, 5, 4, 1]
Output: [-1, 3, -1, 5, 2]
Explanation:
For 3, no greater element to the left, so -1.
For 2, the smallest greater element to the left is 3.
For 5, no greater element to the left, so -1.
For 4, the smallest greater element to the left is 5.
For 1, the smallest greater element to the left is 2.

Input: arr[] = [1,2,3]
Output: [-1, -1, -1]
Explanation: No element has a greater element to its left, so the answer for every element is -1.

Try It Yourself
redirect icon

[Naive Solution] - Using Nested Loops - O(n^2) Time and O(1) Space

For every element, check all previously seen elements and choose the smallest one that is strictly greater than the current element.

  • Initialize the result array with -1.
  • Traverse the array from left to right.
  • For each element, scan all previous elements and keep the smallest value that is greater than the current element.
  • Store the found value in the result array and return it after processing all elements.
C++
#include <climits>
#include <iostream>
#include <vector>
using namespace std;

vector<int> greaterElement(const vector<int> &arr) {
    int n = arr.size();
    vector<int> result(n, -1);

    // Outer loop: Iterate through each element
    for (int i = 0; i < n; i++) {
        int smallestGreater = INT_MAX;

        // Inner loop: Scan all elements to the left
        for (int j = 0; j < i; j++){
            if (arr[j] > arr[i] && arr[j] < smallestGreater)
            {
                smallestGreater = arr[j];
            }
        }

        // If we found a valid element, update the result array
        if (smallestGreater != INT_MAX) {
            result[i] = smallestGreater;
        }
    }

    return result;
}

int main() {
    vector<int> arr = {3, 2, 5, 4, 1};
    int n = arr.size();
    vector<int> ans = greaterElement(arr);
    cout << "[";
    for (int i = 0; i < n; i++) {
        cout << ans[i];
        if (i != n - 1)
            cout << ", ";
    }
    cout << "]";
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;

public class GFG {
    public static ArrayList<Integer> greaterElement(int[] arr) {
        int n = arr.length;
        ArrayList<Integer> result = new ArrayList<>();

        // Initialize result with -1
        for (int i = 0; i < n; i++) {
            result.add(-1);
        }

        // Outer loop: Iterate through each element
        for (int i = 0; i < n; i++) {
            int smallestGreater = Integer.MAX_VALUE;

            // Inner loop: Scan all elements to the left
            for (int j = 0; j < i; j++) {
                if (arr[j] > arr[i] && arr[j] < smallestGreater) {
                    smallestGreater = arr[j];
                }
            }

            // If we found a valid element, update the result
            if (smallestGreater != Integer.MAX_VALUE) {
                result.set(i, smallestGreater);
            }
        }

        return result;
    }

    public static void main(String[] args) {
        int[] arr = {3, 2, 5, 4, 1};
        ArrayList<Integer> ans = greaterElement(arr);

        System.out.println(ans);
    }
}
Python
def greaterElement(arr):
    n = len(arr)
    result = [-1] * n

    # Outer loop: Iterate through each element
    for i in range(n):
        smallestGreater = float('inf')

        # Inner loop: Scan all elements to the left
        for j in range(i):
            if arr[j] > arr[i] and arr[j] < smallestGreater:
                smallestGreater = arr[j]

        # If we found a valid element, update the result array
        if smallestGreater!= float('inf'):
            result[i] = smallestGreater

    return result


if __name__ == '__main__':
    arr = [3, 2, 5, 4, 1]
    ans = greaterElement(arr)
    print('[' + ', '.join(map(str, ans)) + ']')
C#
using System;
using System.Collections.Generic;

class GFG {
    static List<int> greaterElement(int[] arr) {
        int n = arr.Length;
        List<int> result = new List<int>();

        // Initialize result with -1
        for (int i = 0; i < n; i++) {
            result.Add(-1);
        }

        // Outer loop: Iterate through each element
        for (int i = 0; i < n; i++) {
            int smallestGreater = int.MaxValue;

            // Inner loop: Scan all elements to the left
            for (int j = 0; j < i; j++) {
                if (arr[j] > arr[i] && arr[j] < smallestGreater) {
                    smallestGreater = arr[j];
                }
            }

            // If we found a valid element, update the result
            if (smallestGreater != int.MaxValue) {
                result[i] = smallestGreater;
            }
        }

        return result;
    }

    static void Main() {
        int[] arr = { 3, 2, 5, 4, 1 };
        List<int> ans = greaterElement(arr);

        Console.WriteLine("[" + string.Join(", ", ans) + "]");
    }
}
JavaScript
function greaterElement(arr) {
    const n = arr.length;
    const result = Array(n).fill(-1);

    // Outer loop: Iterate through each element
    for (let i = 0; i < n; i++) {
        let smallestGreater = Number.MAX_SAFE_INTEGER;

        // Inner loop: Scan all elements to the left
        for (let j = 0; j < i; j++) {
            if (arr[j] > arr[i] && arr[j] < smallestGreater) {
                smallestGreater = arr[j];
            }
        }

        // If we found a valid element, update the result array
        if (smallestGreater!== Number.MAX_SAFE_INTEGER) {
            result[i] = smallestGreater;
        }
    }

    return result;
}

// Driver code
const arr = [3, 2, 5, 4, 1];
const ans = greaterElement(arr);
console.log('[' + ans.join(', ') + ']');

[Expected Approach] - Using Hash Set

Store the previously seen elements in sorted order so that the smallest element greater than the current value can be found efficiently.

  • Initialize an empty ordered data structure to store the previously visited elements.
  • Traverse the array from left to right.
  • For each element, find the smallest previously visited element that is strictly greater than it.
  • If such an element exists, add it to the answer; otherwise, add -1.
  • Insert the current element into the ordered data structure and continue processing the remaining elements.

Note: Languages like C++, Java, and C# provide built-in ordered data structures. Python and JavaScript do not have a built-in ordered set, so we can implement one using an AVL Tree.

C++
#include <iostream>
#include <vector>
#include <set>

using namespace std;

vector<int> greaterElement(vector<int>& arr) {
    // Set stores elements in sorted order
    set<int> st;

    // Vector to store the final answer
    vector<int> ans;

    for (int num : arr) {

        // Find first element strictly greater
        auto it = st.upper_bound(num);

        // If no greater element exists
        if (it == st.end()) {
            ans.push_back(-1);
        } else {
            // Store greater element
            ans.push_back(*it);
        }

        // Insert current element
        st.insert(num);
    }

    return ans;
}

int main() {
    vector<int> arr = {3, 2, 5, 4, 1};

    vector<int> ans = greaterElement(arr);

    cout << "[";
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i];
        if (i != ans.size() - 1)
            cout << ", ";
    }
    cout << "]" << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    public static ArrayList<Integer> greaterElement(int[] arr) {

        // TreeSet stores elements in sorted order
        TreeSet<Integer> st = new TreeSet<>();

        // ArrayList to store final answer
        ArrayList<Integer> ans = new ArrayList<>();

        for (int num : arr) {

            // Find first element strictly greater
            Integer temp = st.higher(num);

            // If no greater element exists
            if (temp == null) {
                ans.add(-1);
            } else {

                // Store greater element
                ans.add(temp);
            }

            // Insert current element
            st.add(num);
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = {3, 2, 5, 4, 1};

        ArrayList<Integer> ans = greaterElement(arr);

        System.out.println(ans);
    }
}
Python
# Structure of AVL Node
class Node:
    def __init__(self, key):
        self.key = key
        self.left = None
        self.right = None
        self.height = 1


# Returns height of the subtree rooted at node
def getHeight(node):
    if not node:
        return 0
    return node.height


# Returns balance factor = left height - right height
def getBalance(node):
    if not node:
        return 0
    return getHeight(node.left) - getHeight(node.right)


# Performs right rotation
def rightRotate(y):
    x = y.left
    t2 = x.right

    x.right = y
    y.left = t2

    # Update heights after rotation
    y.height = 1 + max(getHeight(y.left), getHeight(y.right))
    x.height = 1 + max(getHeight(x.left), getHeight(x.right))

    return x


# Performs left rotation
def leftRotate(x):
    y = x.right
    t2 = y.left

    y.left = x
    x.right = t2

    # Update heights after rotation
    x.height = 1 + max(getHeight(x.left), getHeight(x.right))
    y.height = 1 + max(getHeight(y.left), getHeight(y.right))

    return y


# Inserts key into AVL tree and balances it if needed
def insert(node, key):
    # Normal BST insertion
    if not node:
        return Node(key)

    if key < node.key:
        node.left = insert(node.left, key)
    elif key > node.key:
        node.right = insert(node.right, key)
    else:
        return node

    # Update height of current node
    node.height = 1 + max(getHeight(node.left),
                          getHeight(node.right))

    # Check if tree became unbalanced
    balance = getBalance(node)

    # Left Left Case
    if balance > 1 and key < node.left.key:
        return rightRotate(node)

    # Right Right Case
    if balance < -1 and key > node.right.key:
        return leftRotate(node)

    # Left Right Case
    if balance > 1 and key > node.left.key:
        node.left = leftRotate(node.left)
        return rightRotate(node)

    # Right Left Case
    if balance < -1 and key < node.right.key:
        node.right = rightRotate(node.right)
        return leftRotate(node)

    return node


# Finds the smallest value strictly greater than key
def getStrictlyGreater(node, key):
    ans = -1

    while node:
        if node.key > key:
            # Current node can be the answer
            ans = node.key
            node = node.left
        else:
            # Look for larger values
            node = node.right

    return ans


def greaterElement(arr):
    root = None
    res = []

    for x in arr:
        # Query before inserting current element
        res.append(getStrictlyGreater(root, x))

        # Insert current element into AVL tree
        root = insert(root, x)

    return res


if __name__ == "__main__":
    arr = [3, 2, 5, 4, 1]
    ans = greaterElement(arr)
    print(ans)
C#
using System;
using System.Collections.Generic;

public class GFG {

    public static List<int> greaterElement(int[] arr) {

        // Stores all previously seen elements in sorted order
        SortedSet<int> seen = new SortedSet<int>();

        List<int> res = new List<int>(arr.Length);

        foreach (int val in arr) {

            // Get all elements strictly greater than val
            var larger = seen.GetViewBetween(val + 1, int.MaxValue);

            // The first element in the view is the answer
            using (var iter = larger.GetEnumerator()) {

                if (iter.MoveNext()) {
                    res.Add(iter.Current);
                } else {
                    res.Add(-1);
                }
            }

            // Insert current element into the set
            seen.Add(val);
        }

        return res;
    }

    public static void Main() {
        int[] arr = { 3, 2, 5, 4, 1 };

        List<int> ans = greaterElement(arr);

        Console.WriteLine("[" + string.Join(", ", ans) + "]");
    }
}
JavaScript
// Structure of AVL Node
class Node {
    constructor(key) {
        this.key = key;
        this.left = null;
        this.right = null;
        this.height = 1;
    }
}

// Returns height of the subtree rooted at node
function getHeight(node) {
    return node === null ? 0 : node.height;
}

// Returns balance factor = left height - right height
function getBalance(node) {
    if (node === null) return 0;
    return getHeight(node.left) - getHeight(node.right);
}

// Performs right rotation
function rightRotate(y) {
    let x = y.left;
    let t2 = x.right;

    x.right = y;
    y.left = t2;

    // Update heights after rotation
    y.height = 1 + Math.max(getHeight(y.left), getHeight(y.right));
    x.height = 1 + Math.max(getHeight(x.left), getHeight(x.right));

    return x;
}

// Performs left rotation
function leftRotate(x) {
    let y = x.right;
    let t2 = y.left;

    y.left = x;
    x.right = t2;

    // Update heights after rotation
    x.height = 1 + Math.max(getHeight(x.left), getHeight(x.right));
    y.height = 1 + Math.max(getHeight(y.left), getHeight(y.right));

    return y;
}

// Inserts key into AVL tree and balances it if needed
function insert(node, key) {
    // Normal BST insertion
    if (node === null) {
        return new Node(key);
    }

    if (key < node.key) {
        node.left = insert(node.left, key);
    } else if (key > node.key) {
        node.right = insert(node.right, key);
    } else {
        return node;
    }

    // Update height of current node
    node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));

    // Check if tree became unbalanced
    let balance = getBalance(node);

    // Left Left Case
    if (balance > 1 && key < node.left.key) {
        return rightRotate(node);
    }

    // Right Right Case
    if (balance < -1 && key > node.right.key) {
        return leftRotate(node);
    }

    // Left Right Case
    if (balance > 1 && key > node.left.key) {
        node.left = leftRotate(node.left);
        return rightRotate(node);
    }

    // Right Left Case
    if (balance < -1 && key < node.right.key) {
        node.right = rightRotate(node.right);
        return leftRotate(node);
    }

    return node;
}

// Finds the smallest value strictly greater than key
function getStrictlyGreater(node, key) {
    let ans = -1;

    while (node !== null) {
        if (node.key > key) {
            // Current node can be the answer
            ans = node.key;
            node = node.left;
        } else {
            // Look for larger values
            node = node.right;
        }
    }

    return ans;
}

function greaterElement(arr) {
    let root = null;
    let res = [];

    for (let x of arr) {
        // Query before inserting current element
        res.push(getStrictlyGreater(root, x));

        // Insert current element into AVL tree
        root = insert(root, x);
    }

    return res;
}

// Driver code
let arr = [3, 2, 5, 4, 1];
let ans = greaterElement(arr);

console.log('[' + ans.join(', ') + ']');


Time Complexity: Traversing the array takes O(n) time, and for each element, searching and inserting into the ordered data structure take O(log n) time. Therefore, the overall time complexity is O(n*log n).
Auxiliary Space: The ordered data structure stores up to n previously visited elements in the worst case, resulting in O(n) auxiliary space.

[Alternate Approach] - Using Segment Tree

Store previously visited elements in a segment tree, allowing the smallest previously visited element greater than the current element to be found efficiently.

  • Perform coordinate compression to map the array values to a smaller index range.
  • Build a segment tree over the compressed indices, where each index stores the corresponding array value if it has been seen.
  • Traverse the array from left to right.
  • For each element, query the segment tree over the range of values greater than the current element to find the smallest previously visited greater element.
  • Store the result, then update the segment tree by marking the current element as visited.
C++
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

class SegmentTree {
    vector<int> tree;
    int n;

public:
    SegmentTree(int size) {
        n = size;
        tree.assign(4 * n, INT_MAX);
    }

    // Updates the value at a compressed index
    void update(int node, int start, int end, int idx, int val) {
        if (start == end) {
            tree[node] = val;
            return;
        }

        int mid = start + (end - start) / 2;

        if (idx <= mid)
            update(2 * node, start, mid, idx, val);
        else
            update(2 * node + 1, mid + 1, end, idx, val);

        // Store minimum value in the current range
        tree[node] = min(tree[2 * node], tree[2 * node + 1]);
    }

    // Returns the minimum value in the given range
    int query(int node, int start, int end, int l, int r) {
        if (r < start || end < l)
            return INT_MAX;

        if (l <= start && end <= r)
            return tree[node];

        int mid = start + (end - start) / 2;

        return min(query(2 * node, start, mid, l, r),
                   query(2 * node + 1, mid + 1, end, l, r));
    }
};

vector<int> greaterElement(vector<int>& arr) {
    int n = arr.size();
    if (n == 0)
        return {};

    // Create sorted list of distinct values
    vector<int> sorted_unique = arr;
    sort(sorted_unique.begin(), sorted_unique.end());
    sorted_unique.erase(unique(sorted_unique.begin(), sorted_unique.end()), sorted_unique.end());

    int U = sorted_unique.size();
    SegmentTree st(U);
    vector<int> ans;

    // Process each element from left to right
    for (int num : arr) {

        // Find compressed index of current element
        int idx = lower_bound(sorted_unique.begin(), sorted_unique.end(), num)
                  - sorted_unique.begin();

        // Query for the smallest greater value
        int res = INT_MAX;
        if (idx + 1 < U) {
            res = st.query(1, 0, U - 1, idx + 1, U - 1);
        }

        // Store the answer
        if (res == INT_MAX)
            ans.push_back(-1);
        else
            ans.push_back(res);

        // Insert current value into the segment tree
        st.update(1, 0, U - 1, idx, num);
    }

    return ans;
}

int main() {
    vector<int> arr = {3, 2, 5, 4, 1};
    vector<int> ans = greaterElement(arr);

    cout << "[";
    for (size_t i = 0; i < ans.size(); i++) {
        cout << ans[i] << (i != ans.size() - 1 ? ", " : "");
    }
    cout << "]" << endl;

    return 0;
}
Java
import java.util.*;

public class GFG {

    static class SegmentTree {
        int[] tree;
        int n;

        SegmentTree(int size) {
            this.n = size;
            this.tree = new int[4 * n];
            Arrays.fill(tree, Integer.MAX_VALUE);
        }

        // Updates the value at a compressed index
        void update(int node, int start, int end, int idx, int val) {
            if (start == end) {
                tree[node] = val;
                return;
            }

            int mid = start + (end - start) / 2;

            if (idx <= mid)
                update(2 * node, start, mid, idx, val);
            else
                update(2 * node + 1, mid + 1, end, idx, val);

            // Store minimum value in the current range
            tree[node] = Math.min(tree[2 * node], tree[2 * node + 1]);
        }

        // Returns the minimum value in the given range
        int query(int node, int start, int end, int l, int r) {
            if (r < start || end < l)
                return Integer.MAX_VALUE;

            if (l <= start && end <= r)
                return tree[node];

            int mid = start + (end - start) / 2;

            return Math.min(query(2 * node, start, mid, l, r),
                            query(2 * node + 1, mid + 1, end, l, r));
        }
    }

    public static ArrayList<Integer> greaterElement(int[] arr) {
        int n = arr.length;
        if (n == 0)
            return new ArrayList<>();

        // Create sorted list of distinct values
        int[] sortedUnique = Arrays.stream(arr).distinct().sorted().toArray();
        int U = sortedUnique.length;

        SegmentTree st = new SegmentTree(U);
        ArrayList<Integer> ans = new ArrayList<>();

        // Process each element from left to right
        for (int num : arr) {

            // Find compressed index of current element
            int idx = Arrays.binarySearch(sortedUnique, num);

            // Query for the smallest greater value
            int res = Integer.MAX_VALUE;
            if (idx + 1 < U) {
                res = st.query(1, 0, U - 1, idx + 1, U - 1);
            }

            // Store the answer
            if (res == Integer.MAX_VALUE)
                ans.add(-1);
            else
                ans.add(res);

            // Insert current value into the segment tree
            st.update(1, 0, U - 1, idx, num);
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = {3, 2, 5, 4, 1};
        System.out.println(greaterElement(arr));
    }
}
Python
import bisect
class SegmentTree:
    def __init__(self, size):
        self.n = size
        self.tree = [float('inf')] * (4 * size)

    # Updates the value at a compressed index
    def update(self, node, start, end, idx, val):
        if start == end:
            self.tree[node] = val
            return

        mid = start + (end - start) // 2

        if idx <= mid:
            self.update(2 * node, start, mid, idx, val)
        else:
            self.update(2 * node + 1, mid + 1, end, idx, val)

        # Store minimum value in the current range
        self.tree[node] = min(self.tree[2 * node], self.tree[2 * node + 1])

    # Returns the minimum value in the given range
    def query(self, node, start, end, l, r):
        if r < start or end < l:
            return float('inf')

        if l <= start and end <= r:
            return self.tree[node]

        mid = start + (end - start) // 2

        return min(self.query(2 * node, start, mid, l, r),
                   self.query(2 * node + 1, mid + 1, end, l, r))


def greater_element(arr):
    if not arr:
        return []

    # Create sorted list of distinct values
    sorted_unique = sorted(set(arr))
    U = len(sorted_unique)

    st = SegmentTree(U)
    ans = []

    # Process each element from left to right
    for num in arr:

        # Find compressed index of current element
        idx = bisect.bisect_left(sorted_unique, num)

        # Query for the smallest greater value
        res = float('inf')
        if idx + 1 < U:
            res = st.query(1, 0, U - 1, idx + 1, U - 1)

        # Store the answer
        if res == float('inf'):
            ans.append(-1)
        else:
            ans.append(res)

        # Insert current value into the segment tree
        st.update(1, 0, U - 1, idx, num)

    return ans


if __name__ == "__main__":
    arr = [3, 2, 5, 4, 1]
    print(greater_element(arr))
C#
using System;
using System.Collections.Generic;
using System.Linq;

class GFG {

    class SegmentTree {
        private int[] tree;
        private int n;

        public SegmentTree(int size) {
            n = size;
            tree = new int[4 * n];
            Array.Fill(tree, int.MaxValue);
        }

        // Updates the value at a compressed index
        public void Update(int node, int start, int end, int idx, int val) {
            if (start == end) {
                tree[node] = val;
                return;
            }

            int mid = start + (end - start) / 2;

            if (idx <= mid)
                Update(2 * node, start, mid, idx, val);
            else
                Update(2 * node + 1, mid + 1, end, idx, val);

            // Store minimum value in the current range
            tree[node] = Math.Min(tree[2 * node], tree[2 * node + 1]);
        }

        // Returns the minimum value in the given range
        public int Query(int node, int start, int end, int l, int r) {
            if (r < start || end < l)
                return int.MaxValue;

            if (l <= start && end <= r)
                return tree[node];

            int mid = start + (end - start) / 2;

            return Math.Min(Query(2 * node, start, mid, l, r),
                            Query(2 * node + 1, mid + 1, end, l, r));
        }
    }

    static List<int> greaterElement(int[] arr) {
        if (arr.Length == 0)
            return new List<int>();

        // Create sorted list of distinct values
        int[] sortedUnique = arr.Distinct().OrderBy(x => x).ToArray();
        int U = sortedUnique.Length;

        SegmentTree st = new SegmentTree(U);
        List<int> ans = new List<int>();

        // Process each element from left to right
        foreach (int num in arr) {

            // Find compressed index of current element
            int idx = Array.BinarySearch(sortedUnique, num);

            // Query for the smallest greater value
            int res = int.MaxValue;
            if (idx + 1 < U) {
                res = st.Query(1, 0, U - 1, idx + 1, U - 1);
            }

            // Store the answer
            if (res == int.MaxValue)
                ans.Add(-1);
            else
                ans.Add(res);

            // Insert current value into the segment tree
            st.Update(1, 0, U - 1, idx, num);
        }

        return ans;
    }

    static void Main() {
        int[] arr = { 3, 2, 5, 4, 1 };
        List<int> ans = greaterElement(arr);

        Console.WriteLine("[" + string.Join(", ", ans) + "]");
    }
}
JavaScript
class SegmentTree {
    constructor(size) {
        this.n = size;
        this.tree = new Array(4 * size).fill(Infinity);
    }

    // Updates the value at a compressed index
    update(node, start, end, idx, val) {
        if (start === end) {
            this.tree[node] = val;
            return;
        }

        const mid = start + Math.floor((end - start) / 2);

        if (idx <= mid) {
            this.update(2 * node, start, mid, idx, val);
        } else {
            this.update(2 * node + 1, mid + 1, end, idx, val);
        }

        // Store minimum value in the current range
        this.tree[node] = Math.min(this.tree[2 * node], this.tree[2 * node + 1]);
    }

    // Returns the minimum value in the given range
    query(node, start, end, l, r) {
        if (r < start || end < l) return Infinity;

        if (l <= start && end <= r) return this.tree[node];

        const mid = start + Math.floor((end - start) / 2);

        return Math.min(
            this.query(2 * node, start, mid, l, r),
            this.query(2 * node + 1, mid + 1, end, l, r)
        );
    }
}

function binarySearch(arr, target) {
    let left = 0, right = arr.length - 1;

    while (left <= right) {
        const mid = left + Math.floor((right - left) / 2);

        if (arr[mid] === target) return mid;

        if (arr[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }

    return -1;
}

function greaterElement(arr) {
    if (arr.length === 0) return [];

    // Create sorted list of distinct values
    const sortedUnique = Array.from(new Set(arr)).sort((a, b) => a - b);
    const U = sortedUnique.length;

    const st = new SegmentTree(U);
    const ans = [];

    // Process each element from left to right
    for (let num of arr) {

        // Find compressed index of current element
        const idx = binarySearch(sortedUnique, num);

        // Query for the smallest greater value
        let res = Infinity;
        if (idx + 1 < U) {
            res = st.query(1, 0, U - 1, idx + 1, U - 1);
        }

        // Store the answer
        if (res === Infinity)
            ans.push(-1);
        else
            ans.push(res);

        // Insert current value into the segment tree
        st.update(1, 0, U - 1, idx, num);
    }

    return ans;
}

// Driver code
const arr = [3, 2, 5, 4, 1];
console.log(greaterElement(arr));


Time Complexity: Traversing the array takes O(n) time. For each element, coordinate compression lookup, segment tree query, and update each take O(log n) time, giving an overall time complexity of O(n*log n).
Auxiliary Space: The segment tree and the compressed array together require O(n) auxiliary space.

Comment