首先,我们需要简单的了解一下单调栈的一些基础知识概念
我们对于栈应该是非常熟悉了, 先进后出。
而 单调栈 简单理解来说就是,从栈底到栈顶, 严格执行 单调递增或递减.
下面我们来看一下单调栈的具体过程是怎样的?
1. 对于单调递增栈来说, 若当前入栈的元素是 a, 将会从栈顶开始遍历, 如果当前遍历的到的元素小于或者等于a, 元素弹出栈, 直到遇到大于 a 或者当前遍历到栈为空, 然后把 a 压入栈中
2. 那么对于 单调递减来说, 每次弹出的是 大于或者 等于 a 的元素
我们可以进行一个实践,去挑战一下自己
496. 下一个更大的元素
解题思路:
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var nextGreaterElement = function(nums1, nums2) {
// nums1 中数字x 的下一个更大元素是指 x 在nums2 中对应位置右侧的 第一个 比 x 大的元素;
// 所以 我们先找出 nums2 中的 右侧是否有 比它 大的元素 记录 或者是 填 -1
// 因为 nums1 真包含于 nums2 所以呢 最后我们找一下对应元素有没有这个值就可以了
// 需要一个栈的存储结构 从后往前走
let stack = [];
// 存放答案的结果数组和一个中间需要暂存数据的map
let tmp = new Map(), res = [];
// 其实就是倒着来
// 2 和 2 比: <= add: -1
// 4 和 2 比:
for (let i = nums2.length-1; i >= 0; i--) {
while(stack.length > 0 && stack[stack.length-1] <= nums2[i]) {
stack.pop();
}
let temp = stack.length === 0 ? -1 : stack[stack.length-1];
tmp.set(nums2[i], temp);
stack.push(nums2[i]);
}
// Map(4) { 2 => -1, 4 => -1, 3 => 4, 1 => 3 }
console.log(tmp);
nums1.forEach(item => {
if (tmp.has(item)) {
res.push(tmp.get(item))
}
})
return res;
};
503. 下一个更大的元素 II
解题思路:
这道题比较难的地方在于如何合理去设计一个循环数组和 是否要给数组加倍的问题
* @param {number[]} nums
* @return {number[]}
*/
var nextGreaterElements = function(nums) {
// 主要是解决如何去在循环数组里去找
// 解决方案: nums[i % n]
// 结果数组
let n = nums.length;
let res = [], stack = [];
// 假装这个数组翻倍了
for (let i = n*2 - 1; i >= 0; i--) {
// while(stack && nums[i % n] <= stack[stack.length-1]) { //error
while(stack && stack[stack.length-1] <= nums[i % n]) {
stack.pop();
}
res[i % n] = stack.length === 0 ? -1 : stack[stack.length-1];
// 这里都需要
stack.push(nums[i % n]);
}
return res;
};