持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
每日刷题 2022.06.01
- leetcode原题链接:leetcode.cn/problems/ne…
- 难度:简单
- 方法:单调栈
题目
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 。
提示
1 <= nums1.length <= nums2.length <= 10000 <= nums1[i], nums2[i] <= 10^4nums1和nums2中所有整数 互不相同nums1中的所有整数同样出现在nums2中
解题思路
- 暴力的思路非常简单,就不多解释了。着重讲解下单调栈的解法,初次学习还请大家多多指教。
- 首先题目中包含寻找下一个更大元素(Next Greater Number)这种字眼的话,题目一般考察的都是单调栈。
- 在考虑如何使用单调栈解决问题之前,先来思考下为什么要使用单调栈?
生活中的举例
- 可以将整个数组想像成是几个高矮不同的学生。那么对于第
i个高度的学生,想要找到其后面(右边)第一个高于他的学生。那么他只需要放眼往后看,可以看到的第一个人就是他后面第一个高于他的学生。(其中比当前学生个子矮的学生会被其他高的挡住看不到) - 根据图中所画可知,当你高度为
3的时候,下一个更大的元素是其后面的下下一个位置的4,直接跳过了1。因为身高为3的学生,放眼往后望去并不能看到高度为1的学生。 - 也就是说对于当前位置
i,其后面比其矮的学生,都不会对最终的答案造成影响,因为答案不可能是他们。那么我们就可以使用单调栈,维护一个单调栈,来存储当前i的下一个更大值。
解题(原创图)
- 具体的步骤(如下图所示,假设
nums2 = [1,6,2,3,5,7]) - 依靠于
nums2数组中不存在重复的数字,因此对于nums2中的每一个元素求解其右边下一个更大的元素后,只需要再遍历一遍nums1,将每个值对应的下一个更大元素填入数组中即可。
AC代码
var nextGreaterElement = function(nums1, nums2) {
// [4,1,2] 最后使用map来查找对应的值
// [5,1,3,4,2] 先处理这个问题
// -1,3,4,-1,-1
// stack: [5]
// 时刻维护一个单调栈,一般都是单调递增,但是这里的单调递增并不是完全定以上的单调递增
let s = [], m = new Map();
const n1 = nums1.length, n2 = nums2.length;
for(let i = n2 - 1; i >= 0; i--) {
// 逆序遍历,找到右边的下一个更大元素
// 不满足的时候,需要进行循环遍历
let cur = nums2[i];
while(!(s.length == 0) && cur >= s[s.length - 1]) {
// 循环遍历
s.pop();
}
// 循环寻找完成后,可能满足 也有可能不满足
let res = s.length == 0 ? -1 : s[s.length - 1];
s.push(cur);
m.set(cur, res);
}
let ans = [];
// 最后将nums1中对应的数值的下一个更大值填入到ans数组中
for(let i = 0; i < n1; i++) {
ans[i] = m.get(nums1[i]);
}
return ans;
};
总结
- 单调栈主要用于寻找下一个更大元素(Next Greater Number)