Next Greater Element

Hero Image

DT

Dhaval Trivedi

Co-founder, Airtribe

Problem Overview

The LeetCode problem "Next Greater Element I" is a classic problem that utilizes both Stack and Queue data structures. The problem provides two integer arrays nums1 and nums2 where nums1 is a subset of nums2. The task is to find the next greater number for each element in nums1 within the array nums2. The next greater number of a number x in nums2 is the first greater number to its right; if it doesn't exist, return -1 for this number.

Problem Statement

You are given two arrays (with no duplicates) nums1 and nums2 without duplicates, in which nums1 is a subset of nums2. You need to find the next greater element for each element in nums1 in the array nums2.

Example:

Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
Output: [-1,3,-1]
Explanation:
For the number 4 in second array, there is no greater number to the right, so output -1.
For the number 1 in second array, the next greater number is 3.
For the number 2 in second array, there is no greater number to the right, so output -1.

Understanding the Problem

We need to find the next greater element for each element in nums1 using the context of nums2. The challenge revolves around efficiently finding this next greater element without resorting to the naive approach of comparing each element to all others.

Key DSA Concepts and Theory

Stack

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. It allows adding and removing of elements in a particular order. Stacks are used in problems where the most recent addition is needed first, similar to the problem's requirement of finding the next greater element.

Maps or Hash Tables

A map (or hash table) allows for fast and efficient lookup of values based on a key. In this problem, it can help in quickly relating each element of nums1 to its next greater element determined from nums2.

Solution Approach

The solution involves using a stack to traverse the nums2 array and keep track of elements for which a greater element has not yet been encountered. We will also use a hash map to store the mappings of each element to their next greater element.

Here's a detailed step-by-step solution:

  1. Initialize an empty stack and a map (or hash table).
  2. Traverse the nums2 array:
    • For each element num, while the stack is not empty and the top element of the stack is less than num, pop the stack. For every popped element, the num is its next greater element. Store this relationship in the map.
    • Push num onto the stack.
  3. After processing nums2, use the map to resolve each element in nums1 to its next greater element or to -1 if no such element exists.

C++ Code

#include <vector>
#include <unordered_map>
#include <stack>

std::vector<int> nextGreaterElement(std::vector<int>& nums1, std::vector<int>& nums2) {
    std::unordered_map<int, int> nge_map;
    std::stack<int> st;
    
    for (int num : nums2) {
        while (!st.empty() && st.top() < num) {
            nge_map[st.top()] = num;
            st.pop();
        }
        st.push(num);
    }
    
    std::vector<int> result;
    for (int num : nums1) {
        result.push_back(nge_map.count(num) ? nge_map[num] : -1);
    }
    
    return result;
}

Java Code

import java.util.HashMap;
import java.util.Stack;

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        HashMap<Integer, Integer> ngeMap = new HashMap<>();
        Stack<Integer> stack = new Stack<>();
        
        for (int num : nums2) {
            while (!stack.isEmpty() && stack.peek() < num) {
                ngeMap.put(stack.pop(), num);
            }
            stack.push(num);
        }
        
        int[] result = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            result[i] = ngeMap.getOrDefault(nums1[i], -1);
        }
        
        return result;
    }
}

Time and Space Complexity Analysis

  • Time Complexity: O(n + m), where n is the length of nums1, and m is the length of nums2. We traverse each array once.
  • Space Complexity: O(m) for the extra space used by the stack and map, which in the worst-case scenario, both can grow up to the size of nums2.

Common Mistakes to Avoid

  • Not initializing the map correctly or handling the mapping with default values could lead to incorrect results.
  • Mismanaging the stack operations, particularly forgetting to pop elements or pushing incorrect elements.
  • Directly modifying input arrays instead of utilizing a new result array.

Similar Problems on LeetCode

Here are some similar problems that can be found on LeetCode:

  • Next Greater Element II (Problem 503): A variation that considers the array in a circular manner.
  • Next Greater Element III (Problem 556): A puzzle involving digits and permutations rather than array elements.

Additional Resources and References

  1. LeetCode Discuss - Explanation and Solutions for Next Greater Element I
  2. GeeksforGeeks - Stack Data Structure
  3. Java Documentation on Stack

This problem is a great example to understand the application of stacks in solving algorithmic problems and enhances one's ability to relate between different arrays using hash maps efficiently.