leetcode---单调栈

183 阅读2分钟

首先,我们需要简单的了解一下单调栈的一些基础知识概念

我们对于应该是非常熟悉了, 先进后出。

单调栈 简单理解来说就是,从栈底到栈顶, 严格执行 单调递增或递减.

下面我们来看一下单调栈的具体过程是怎样的?

1. 对于单调递增栈来说, 若当前入栈的元素是 a, 将会从栈顶开始遍历, 如果当前遍历的到的元素小于或者等于a, 元素弹出栈, 直到遇到大于 a 或者当前遍历到栈为空, 然后把 a 压入栈中

2. 那么对于 单调递减来说, 每次弹出的是 大于或者 等于 a 的元素

我们可以进行一个实践,去挑战一下自己

496. 下一个更大的元素

496.jpg

解题思路:

/**
 * @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;
};

496. 下一个更大的元素

503. 下一个更大的元素 II

image.png

解题思路:

这道题比较难的地方在于如何合理去设计一个循环数组和 是否要给数组加倍的问题

 * @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;
};

503 下一个更大的元素 II