🧠
Optimized Stack with Early Exit for nums1
💡 This approach is a minor optimization that stops processing nums2 early if all nums1 elements have found their next greater element, saving some unnecessary work.
Intuition
Track how many nums1 elements remain to find next greater; once all are found, stop processing nums2.
Algorithm
- Create a set of nums1 elements to track which need next greater.
- Initialize stack and hashmap as before.
- Iterate over nums2:
- While stack top is smaller than current num, pop and record next greater; if popped element is in nums1 set, remove it.
- If nums1 set is empty, break early.
- Push current num onto stack.
- Assign -1 to remaining elements in stack.
- Return next greater for nums1 elements from hashmap.
💡 This reduces unnecessary processing when nums1 is much smaller than nums2.
from typing import List
def nextGreaterElement(nums1: List[int], nums2: List[int]) -> List[int]:
stack = []
next_greater_map = {}
nums1_set = set(nums1)
for num in nums2:
while stack and num > stack[-1]:
smaller = stack.pop()
next_greater_map[smaller] = num
if smaller in nums1_set:
nums1_set.remove(smaller)
if not nums1_set:
break
stack.append(num)
if not nums1_set:
break
while stack:
next_greater_map[stack.pop()] = -1
return [next_greater_map[x] for x in nums1]
# Driver code
if __name__ == '__main__':
print(nextGreaterElement([4,1,2], [1,3,4,2])) # Output: [-1,3,-1]
Line Notes
nums1_set = set(nums1)Track which nums1 elements still need next greater
while stack and num > stack[-1]:Pop smaller elements and record next greater
if smaller in nums1_set:Remove found elements from tracking set
if not nums1_set: breakStop early if all nums1 elements found
import java.util.*;
public class NextGreaterElement {
public static int[] nextGreaterElement(int[] nums1, int[] nums2) {
Set<Integer> nums1Set = new HashSet<>();
for (int num : nums1) nums1Set.add(num);
Map<Integer, Integer> nextGreaterMap = new HashMap<>();
Deque<Integer> stack = new ArrayDeque<>();
for (int num : nums2) {
while (!stack.isEmpty() && num > stack.peek()) {
int smaller = stack.pop();
nextGreaterMap.put(smaller, num);
if (nums1Set.contains(smaller)) {
nums1Set.remove(smaller);
if (nums1Set.isEmpty()) break;
}
}
stack.push(num);
if (nums1Set.isEmpty()) break;
}
while (!stack.isEmpty()) {
nextGreaterMap.put(stack.pop(), -1);
}
int[] result = new int[nums1.length];
for (int i = 0; i < nums1.length; i++) {
result[i] = nextGreaterMap.get(nums1[i]);
}
return result;
}
public static void main(String[] args) {
int[] res = nextGreaterElement(new int[]{4,1,2}, new int[]{1,3,4,2});
System.out.println(Arrays.toString(res)); // [-1,3,-1]
}
}
Line Notes
Set<Integer> nums1Set = new HashSet<>();Track nums1 elements needing next greater
while (!stack.isEmpty() && num > stack.peek()) {Pop smaller elements and record next greater
if (nums1Set.contains(smaller)) {Remove found elements from tracking set
if (nums1Set.isEmpty()) break;Stop early if all nums1 elements found
#include <iostream>
#include <vector>
#include <stack>
#include <unordered_map>
#include <unordered_set>
using namespace std;
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> nextGreaterMap;
unordered_set<int> nums1Set(nums1.begin(), nums1.end());
stack<int> st;
for (int num : nums2) {
while (!st.empty() && num > st.top()) {
int smaller = st.top();
st.pop();
nextGreaterMap[smaller] = num;
if (nums1Set.count(smaller)) {
nums1Set.erase(smaller);
if (nums1Set.empty()) break;
}
}
st.push(num);
if (nums1Set.empty()) break;
}
while (!st.empty()) {
nextGreaterMap[st.top()] = -1;
st.pop();
}
vector<int> result;
for (int x : nums1) {
result.push_back(nextGreaterMap[x]);
}
return result;
}
int main() {
vector<int> nums1 = {4,1,2};
vector<int> nums2 = {1,3,4,2};
vector<int> res = nextGreaterElement(nums1, nums2);
for (int val : res) cout << val << ' '; // -1 3 -1
cout << endl;
return 0;
}
Line Notes
unordered_set<int> nums1Set(nums1.begin(), nums1.end());Track nums1 elements needing next greater
while (!st.empty() && num > st.top()) {Pop smaller elements and record next greater
if (nums1Set.count(smaller)) {Remove found elements from tracking set
if (nums1Set.empty()) break;Stop early if all nums1 elements found
function nextGreaterElement(nums1, nums2) {
const stack = [];
const nextGreaterMap = new Map();
const nums1Set = new Set(nums1);
for (const num of nums2) {
while (stack.length && num > stack[stack.length - 1]) {
const smaller = stack.pop();
nextGreaterMap.set(smaller, num);
if (nums1Set.has(smaller)) {
nums1Set.delete(smaller);
if (nums1Set.size === 0) break;
}
}
stack.push(num);
if (nums1Set.size === 0) break;
}
while (stack.length) {
nextGreaterMap.set(stack.pop(), -1);
}
return nums1.map(x => nextGreaterMap.get(x));
}
// Test
console.log(nextGreaterElement([4,1,2], [1,3,4,2])); // [-1,3,-1]
Line Notes
const nums1Set = new Set(nums1);Track nums1 elements needing next greater
while (stack.length && num > stack[stack.length - 1]) {Pop smaller elements and record next greater
if (nums1Set.has(smaller)) {Remove found elements from tracking set
if (nums1Set.size === 0) break;Stop early if all nums1 elements found
TimeO(n + m) same as previous approach but with potential early exit
SpaceO(n) for stack and hashmap
Early exit can save time if nums1 is small compared to nums2, but worst case remains linear.
💡 This optimization is useful when nums1 is much smaller than nums2, reducing unnecessary work.
Interview Verdict: Accepted; minor optimization over standard stack approach
Good to mention if interviewer asks about improvements, but not required.