【单调栈】739. 每日温度、496. 下一个更大元素 I

提示:努力生活,开心、快乐的一天

文章目录

  • 739. 每日温度
    • 解题思路
    • 遇到的问题
    • 代码实现
    • 题目总结
  • 496. 下一个更大元素 I
    • 解题思路
    • 遇到的问题
    • 代码实现
    • 题目总结
  • 今日心得


739. 每日温度

题目链接:739. 每日温度

解题思路

  1. 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。
  2. 单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。
  3. 使用单调栈的时候首先要明确如下几点:
    1、 单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。
    2、 单调栈里元素是递增呢? 还是递减呢?
    使用递增循序(再强调一下是指从栈头到栈底的顺序),因为只有递增的时候,栈里要加入一个元素i的时候,才知道栈顶元素在数组中右面第一个比栈顶元素大的元素是i。

遇到的问题

  1. 熟悉单调栈的含义

代码实现

单调栈

var dailyTemperatures = function(temperatures) {
    const n = temperatures.length;
    const res = Array(n).fill(0);
    const stack = [];  // 递增栈:用于存储元素右面第一个比他大的元素下标
    stack.push(0);
    for (let i = 1; i < n; i++) {
        // 栈顶元素
        const top = stack[stack.length - 1];
        if (temperatures[i] < temperatures[top]) {
            stack.push(i);
        } else if (temperatures[i] === temperatures[top]) {
            stack.push(i);
        } else {
            while (stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) {
                const top = stack.pop();
                res[top] = i - top;
            }
            stack.push(i);
        }
    }
    return res;
};

题目总结

三种情况都做了详细的分析。
情况一:当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
情况二:当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
情况三:当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
通过以上过程,大家可以自己再模拟一遍,就会发现:只有单调栈递增(从栈口到栈底顺序),就是求右边第一个比自己大的,单调栈递减的话,就是求右边第一个比自己小的。


496. 下一个更大元素 I

题目链接:496. 下一个更大元素 I

解题思路

  1. 在739. 每日温度 (opens new window)中是求每个元素下一个比当前元素大的元素的位置。本题则是说nums1 是 nums2的子集,找nums1中的元素在nums2中下一个比当前元素大的元素。
  2. 题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1。
    在遍历nums2的过程中,我们要判断nums2[i]是否在nums1中出现过,因为最后是要根据nums1元素的下标来更新result数组。
    注意题目中说是两个没有重复元素 的数组 nums1 和 nums2。
  3. 栈头到栈底的顺序,要从小到大,也就是保持栈里的元素为递增顺序。只要保持递增,才能找到右边第一个比自己大的元素。
  4. 接下来就要分析如下三种情况,一定要分析清楚。
    情况一:当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
    此时满足递增栈(栈头到栈底的顺序),所以直接入栈。
    情况二:当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
    如果相等的话,依然直接入栈,因为我们要求的是右边第一个比自己大的元素,而不是大于等于!
    情况三:当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
    此时如果入栈就不满足递增栈了,这也是找到右边第一个比自己大的元素的时候。
    判断栈顶元素是否在nums1里出现过,(注意栈里的元素是nums2的元素),如果出现过,开始记录结果。

遇到的问题

代码实现

暴力解法

var nextGreaterElement = function (nums1, nums2) {
  let stack = [];
  let map = new Map();
  for (let i = 0; i < nums2.length; i++) {
    while (stack.length && nums2[i] > nums2[stack[stack.length - 1]]) {
      let index = stack.pop();
      map.set(nums2[index], nums2[i]);
    }
    stack.push(i);
  }

  let res = [];
  for (let j = 0; j < nums1.length; j++) {
    res[j] = map.get(nums1[j]) || -1;
  }

  return res;
};

题目总结

三种情况需要特殊分析

今日心得

初次接触单调栈

你可能感兴趣的:(算法,算法)