nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x ****大的元素。
给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。
对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1
返回一个长度为 nums1.length 的数组 **ans **作为答案,满足 **ans[i] **是如上所述的 下一个更大元素
示例 1:
输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
- 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
- 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
示例 2:
输入:nums1 = [2,4], nums2 = [1,2,3,4].
输出:[3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:
- 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
- 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。
题解:
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var nextGreaterElement = function (nums1, nums2) {
// // 方法一:暴力法
const n = nums1.length, m = nums2.length;
const ans = []
for (let i = 0; i < n; i++) {
// 获取当前数在nums2中位置
let j = nums2.indexOf(nums1[i])
// 获取下一位置
let k = j + 1
// 下一位置小于nums2 并且下一位置的值小于当前位置值时
// 遍历寻找大于当前位置值得数
while (k < m && nums2[k] < nums2[j]) {
++k
}
// 当找不到大于前位置值的时取-1
ans[i] = k < m ? nums2[k] : -1;
}
// return ans;
// 方法二:单调栈
// 1、创建一个临时栈,一个哈希表,然后遍历 nums2。
// 2、若当前栈无数据,则当前数字入栈备用。
// 3、若当前栈有数据,则用当前数字与栈顶比较:
// 3.1 当前数字 > 栈顶,代表栈顶对应下一个更大的数字就是当前数字,
// 则将该组数字对应关系,记录到哈希表。
// 3.2 当前数字 < 栈顶,当前数字压入栈,供后续数字判断使用。
// 4、这样,我们就可以看到哈希表中存在部分 nums2 数字的对应关系了,
// 而栈中留下的数字,代表无下一个更大的数字,我们全部赋值为−1 ,然后存入哈希表即可。
// 5、遍历 nums1,直接询问哈希表拿对应关系即可。
let map = new Map(), stack = [], ans = [];
nums2.forEach(item => {
while (stack.length && item > stack[stack.length - 1]) {
map.set(stack.pop(), item)
};
stack.push(item);
});
stack.forEach(item => map.set(item, -1));
nums1.forEach(item => ans.push(map.get(item)));
return ans;
};