The next greater element of some element x in an array is the first greater element that is to the right of x in the array.
You are given two 0-indexed integer arrays nums1 and nums2, where nums1 is a subset of nums2. nums2 contains unique elements.
For each 0 <= i < nums1.length, find the index j such that nums1[i] == nums2[j] and determine the next greater element of nums2[j] in nums2. If there is no next greater element, then the answer for this query is -1.
Example 1:
Input: nums1 = [4,1,2], nums2 = [1,3,4,2]
Output: [-1,3,-1]Explanation:
4.3 is the next greater element for 1.2.Example 2:
Input: nums1 = [2,4], nums2 = [1,2,3,4]
Output: [3,-1]Explanation:
3 is the next greater element for 2.4.Constraints:
1 <= nums1.length <= nums2.length <= 10000 <= nums1[i], nums2[i] <= 10,000nums1 and nums2 are unique.nums1 also appear in nums2.Follow up: Could you find an O(nums1.length + nums2.length) solution?
Before attempting this problem, you should be comfortable with:
For each element in nums1, we need to find it in nums2 and then look for the first larger element to its right. The simplest approach scans nums2 from right to left: track the largest element seen so far that is greater than our target. When we hit the target element, we have our answer.
This works but is inefficient since we repeat the scan for every element in nums1.
nums1:nums2 from right to left.nums2, stop and record the tracked greater element (or -1 if none found).class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
n = len(nums2)
res = []
for num in nums1:
nextGreater = -1
for i in range(n - 1, -1, -1):
if nums2[i] > num:
nextGreater = nums2[i]
elif nums2[i] == num:
break
res.append(nextGreater)
return resWhere is the size of the array and is the size of the array .
Instead of scanning from the end each time, we can iterate through nums2 from left to right. For each element that appears in nums1, we look ahead to find the next greater element. A hash map stores the index of each nums1 element, so we can quickly check if a number from nums2 is one we care about.
This is still O(m * n) in the worst case, but we skip elements not in nums1.
nums1 to its index.-1 values.nums2. For each element that exists in the hash map:class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1Idx = {num : i for i, num in enumerate(nums1)}
res = [-1] * len(nums1)
for i in range(len(nums2)):
if nums2[i] not in nums1Idx:
continue
for j in range(i + 1, len(nums2)):
if nums2[j] > nums2[i]:
idx = nums1Idx[nums2[i]]
res[idx] = nums2[j]
break
return resWhere is the size of the array and is the size of the array .
A monotonic stack solves this problem in linear time. We iterate through nums2 and maintain a stack of elements that have not yet found their next greater element. When we encounter a larger element, it becomes the "next greater" for all smaller elements on the stack.
The stack maintains decreasing order from bottom to top. When a new element is larger than the stack top, we pop elements and record the current element as their next greater. We only push elements that are in nums1 since those are the only ones we need answers for.
nums1 to its index.-1 values.nums2 with a stack:nums1, and set result[index] to current element.nums1, push it onto the stack.class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
nums1Idx = {num : i for i, num in enumerate(nums1)}
res = [-1] * len(nums1)
stack = []
for i in range(len(nums2)):
cur = nums2[i]
while stack and cur > stack[-1]:
val = stack.pop()
idx = nums1Idx[val]
res[idx] = cur
if cur in nums1Idx:
stack.append(cur)
return resWhere is the size of the array and is the size of the array .
The next greater element must be found in nums2, to the right of where the element appears in nums2. Some solutions mistakenly look for the next greater element within nums1 or search to the left instead of right in nums2.
The stack optimization only needs to track elements from nums1 that are waiting for their next greater element. Pushing every element from nums2 onto the stack works but uses unnecessary space. Only push elements that exist in the nums1 lookup map.