496.下一个更大元素

给你两个 没有重复元素 的数组 nums1nums2 ,其中nums1nums2 的子集。

请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 xnums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1

示例 1:

1
2
3
4
5
6
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1

Solution

我们可以先预处理 nums2,使查询nums1中的每个元素在nums2中对应位置的右边的第一个更大的元素值时不需要再遍历nums2。于是,我们将题目分解为两个子问题:

  • 第 1 个子问题:如何更高效地计算nums2中每个元素右边的第一个更大的值;
  • 第 2 个子问题:如何存储第 1 个子问题的结果。

针对第一个问题,我们可以逆序遍历nums2,同时将结果入栈,如当前元素大于栈顶元素,则让栈顶元素出栈,这种结构称为 单调栈

针对第二个问题,因为题目规定了nums2是没有重复元素的,所以我们可以使用哈希表来解决第 2个子问题,将元素值与其右边第一个更大的元素值的对应关系存入哈希表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
// 使用HashMap来存储nums2中每个元素及其下一个更大元素的映射
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
// 使用栈来帮助找出下一个更大的元素
Deque<Integer> stack = new ArrayDeque<Integer>();

// 从右向左遍历nums2数组
for (int i = nums2.length - 1; i >= 0; --i) {
int num = nums2[i];
// 如果栈不为空且栈顶元素小于或等于当前元素num,则弹出栈顶元素
// 这样做的目的是为了保留那些可能是下一个更大元素的候选项
while (!stack.isEmpty() && num >= stack.peek()) {
stack.pop();
}
// 对当前元素num,其下一个更大元素放入map中
// 如果栈为空,说明右侧没有更大的元素,因此映射为-1
map.put(num, stack.isEmpty() ? -1 : stack.peek());
// 将当前元素推入栈中,为后续元素的比较做准备
stack.push(num);
}

// 初始化结果数组,长度与nums1相同
int[] res = new int[nums1.length];
// 遍历nums1数组,根据map中的映射找出每个元素的下一个更大元素
for (int i = 0; i < nums1.length; ++i) {
res[i] = map.get(nums1[i]);
}
// 返回结果数组
return res;
}
}