Next Greater Element II: Two Approaches

Next Greater Element II: Two Approaches

First Solution

Brute force approach. Time complexity O(N²).

For each element, scan from the start and record indices of larger elements. When we’re to the left of the target element, always update. When we’re to the right, break once we find a match. Set to -1 if no match exists.

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> res;
        for(int i=0;i<nums.size();++i) {
            int idx = -2;
            for(int j=0;j<nums.size();++j) {
                if (nums[j]>nums[i]) {
                    if (j < i && idx < 0) {
                        idx = j;
                    } else if (j > i) {
                        idx = j;
                        break;
                    }
                }
            }
            
            if (idx < 0)
                res.push_back(-1);
            else
                res.push_back(nums[idx]);
        }
        return res;
    }
};

Optimal Solution Using Stack

Time complexity: O(N) Space complexity: O(N)

#define MAX_NUMS 10000

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        vector<int> res(nums.size(), -1);
        bitset<MAX_NUMS> bs;
        stack<int> s;
        
        // Start from the right side
        for(int j=nums.size()-1;j>=0;--j) {
            // Scan from right to left, keep largest element at top
            while (!s.empty() && nums[s.top()] <= nums[j]) s.pop();

            if (!s.empty()) {
                res[j] = nums[s.top()];
                // Mark elements found in first pass
                bs[j] = 1;
            }
            
            s.push(j);
        }
        
        // Use existing stack to find remaining elements
        for(int j=nums.size()-1;j>0;--j) {
            // Only look for those not found yet
            if (bs[j] == 0) {
                while(!s.empty() && nums[j] >= nums[s.top()]) s.pop();
                
                if (!s.empty()) res[j] = nums[s.top()];
            }
        }
        
        return res;
    }
};

Think of the array as segmented. Circular search splits the array like this:

A….B element….C becomes B element ….C A…

Scanning from right to left saves computation.

Key Insight

I optimized space complexity beyond the standard solution by using a compact bitset to mark found elements, reducing memory overhead while maintaining optimal time performance.

#stack