2Brute2Best
🔥0

Next Greater Element I

Easy·LeetCode #496Basic Anchor
LeetCode
30-Second Mental ModelMonotonic Stack (decreasing) — next greater element
Complexity:O(N · M)→O(N + M)
Key Insight

Read nums2 once, left to right. Keep a stack of numbers that are still waiting for a bigger number. When x arrives, pop every waiting number smaller than x; x is the first bigger number each of them has met, so it is their answer. Store it in a hash map value → next greater. Then push x. Numbers left at the end get -1. Finally answer nums1 with one lookup each.

Core Validity Invariant

The stack always decreases from bottom to top. Every number on it is still waiting, and the top is the smallest waiting number, so it is the first one a bigger arrival can answer.

01

Problem

You get two arrays of distinct numbers, nums1 and nums2. Every number in nums1 also appears somewhere in nums2.

For a number x, its next greater element is the first number to the right of x in nums2 that is bigger than x. If there is none, the answer is -1.

For each number in nums1, return its next greater element (looked up in nums2), in the same order as nums1.

Input

Two integer arrays nums1 and nums2. All values are distinct, and nums1 is a subset of nums2.

Output

An array ans of the same length as nums1, where ans[k] is the next greater element of nums1[k] in nums2, or -1.

Example 1
Input: nums1 = [4, 1, 2], nums2 = [1, 3, 4, 2]
Output: [-1, 3, -1]

In nums2, nothing to the right of 4 is bigger. The first number after 1 that is bigger is 3. 2 is the last number, so nothing is after it.

Example 2
Input: nums1 = [2, 4], nums2 = [1, 2, 3, 4]
Output: [3, -1]

After 2 comes 3, which is bigger. 4 is the last number.

Constraints
  • • 1 ≤ nums1.length ≤ nums2.length ≤ 1000
  • • 0 ≤ nums1[i], nums2[i] ≤ 10^4
  • • All values in nums1 and nums2 are distinct
  • • Every value of nums1 appears in nums2
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Does the answer depend on nums1 at all, or only on where the number sits in nums2?

  2. 2.

    If I knew the next greater element for every value of nums2, how would I answer nums1 fast?

  3. 3.

    When a big number arrives while reading nums2 left to right, which earlier numbers has it just answered?

  4. 4.

    Once a number has found its next greater element, do I ever need it again?

  5. 5.

    If 5 is still waiting and then 3 arrives, can 3 be the answer for 5? Can 3 still need an answer of its own?

03

Brute force approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFor each nums1 value, locate it in nums2 and walk right to the first bigger numberO(N · M)O(1)
OptimalOne pass over nums2; a bigger arrival pops and answers every smaller waiting valueO(N + M)O(M)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “first number to the right that is bigger”Next greater element → monotonic stack, decreasing.
  • “distinct numbers”A value can be a map key, so answers can be stored by value instead of by index.
  • “nums1 is a subset of nums2”Compute answers for all of nums2 once, then just look up the ones nums1 asks for.
For each element+first bigger value to the right+one left-to-right pass→Monotonic Stack (decreasing) — next greater element

This is the anchor of the sub-pattern: the plain "next greater" question. The only extra is the hash map, because answers are asked for by value. Daily Temperatures asks for a distance instead (so the stack holds indices), Next Greater Element II makes the array circular, and Car Fleet hides the same "who blocks me" idea behind arrival times.

10

Don't make this mistake

Using an increasing stack (popping while top > x)
✗ while (!st.empty() && st.back() > x) { nextGreater[st.back()] = x; st.pop_back(); }
✓ while (!st.empty() && st.back() < x) { nextGreater[st.back()] = x; st.pop_back(); }

Pattern-confusion trap. Popping when the new number is smaller finds the next smaller element, a different sub-pattern. Ask: "who does x answer?" For next greater, x answers the numbers smaller than it, so pop while top < x, which keeps the stack decreasing.

Using if instead of while
✗ if (!st.empty() && st.back() < x) { ... }
✓ while (!st.empty() && st.back() < x) { ... }

One big number can answer many waiting numbers. In [6, 5, 4, 7], 7 answers 4, 5 and 6. With if, only 4 gets its answer.

Forgetting the leftovers
✗ for (int x : nums1) ans.push_back(nextGreater[x]); // never set the leftovers
✓ for (int v : st) nextGreater[v] = -1; // before the lookups

With unordered_map, operator[] on a missing key gives 0, not -1. Numbers that never found a bigger one would wrongly return 0.

Running the stack over nums1

The next greater element is defined by positions in nums2. nums1 is in a different order, so a stack over nums1 answers the wrong question. Build the map from nums2, then use nums1 only for lookups.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Monotonic Stack translate into production architectures and low-level memory mechanics.