Watch how a monotonic decreasing stack efficiently finds the next greater element for each value in one pass.
Monotonic Stack LeetCode 496 ↗ Easynums1 and nums2 where nums1 is a subset of nums2,
find the next greater element for each element in nums1.nums2, the next greater element is the first element to the right
that is larger. If no such element exists, the answer is -1.nums1 = [4,1,2], nums2 = [1,3,4,2]: the next greater element of
1 is 3, 4 has none (-1), and 2 has none (-1).
Result: [-1, 3, -1].
fun nextGreaterElement(nums1: IntArray, nums2: IntArray): IntArray { val stack = ArrayDeque<Int>() val nextGreater = mutableMapOf<Int, Int>() for (num in nums2) { while (stack.isNotEmpty() && stack.last() < num) { nextGreater[stack.removeLast()] = num } stack.addLast(num) } return IntArray(nums1.size) { nextGreater.getOrDefault(nums1[it], -1) } }
Instead of searching for the next greater element for every value using nested loops (O(n²)),
we use a monotonic decreasing stack to solve the problem in a single pass through nums2.
The stack holds elements that have not yet found their next greater element. When we encounter a larger value,
it becomes the answer for all smaller elements sitting on the stack.
next_greater.num in nums2.num:
pop the top element and record next_greater[popped] = num.-1).nums1 by looking up each value in the map: next_greater.get(n, -1).The stack maintains a decreasing order from bottom to top. When a new element arrives that is larger than the stack top, we know this element is the first greater element to the right for whatever is on top. We keep popping until the stack property is restored. This guarantees each element is pushed and popped at most once, giving us amortized O(1) per element.
Each element in nums2 is pushed onto the stack exactly once and popped at most once,
so the total number of stack operations is O(n). The hash map stores at most n entries.
Building the result for nums1 takes O(m) where m is the length of nums1.