leetcode hot100之每日温度(739)解析

124 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情


前言

  • leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。
  • 本题使用了单调栈,简单介绍下单调栈就是单调递增或单调减的,跟单调队列差不多,但是只用到它的一端。这种数据结构可以帮助我们在很多场景下解决问题。

leetcode739题(每日温度)

本文来讲hot100第739题,每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

示例:

输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
输入: temperatures = [30,60,90]
输出: [1,1,0]
输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]

分析

通过分析题目可知几个信息点

  1. 下一个更高的温度就是下一个比当前位置的数字大的值
  2. 不存在返回0

我们分析题意有2种解法

  1. 暴力循环即可,第一次循环外面的数组,第二次基于当前数,继续遍历查找下一个比当前大的值,本题既然是Medium,那么肯定不希望我们是用暴力解法。
  2. 单调栈解决,我们正常遍历每日的温度,并维护一个单调栈。(可以理解拿当前的值与栈内元素进行查找),又因为我们要算出升温日的天数,所以栈中存储下标。
    • 栈是空的 或者 当前值小于栈顶,我们直接入栈。
    • 如果栈是有值的,并且值大于栈顶元素,说明找到了下一个升温日,需要出栈,并且把天数计算出来,继续判断栈顶元素。

代码

暴力解法

const ans = [], len = temperatures.length
for (let i = 0; i < len; i ++ ) {
    let nextIndex = i + 1
    while (nextIndex < len) {
      if (temperatures[nextIndex] > temperatures[i]) {
        break
      }
      nextIndex ++
    }
    // 如果找到最后一个,还是没有大于当前数字,说明没有更高的温度,我们就返回0
    // 有最高的温度,直接用nextIndex - index的差值就好了
    ans.push(nextIndex === len ? 0 : nextIndex - i)
  }
 return ans

单调栈(按照我们的分析直接给出代码)

let n = temperatures.length;
let res = new Array(n).fill(0);
let stack = [0]

// 这里正向遍历温度
for (let i = 1; i < n; i++) {
    // 这里遍历单调栈,如果当前温度大于栈顶温度,说明找到升温日,则执行循环
    while (stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) {
      // 栈顶元素(也是i天温度的下标)
      const top = stack.pop()
      // 找到的升温日,我们把下标存储
      res[top] = i - top
    }
    // 正常遍历,需要把当前的下标入栈
    stack.push(i)
  }

return res;

结语

  • 暴力法,双层循环,我们的时间复杂度是O(n ^ 2),空间复杂度是O(n),n为数组的长度。
  • 单调栈,我们只会正向遍历一边温度,所以时间复杂度是O(n),由于需要单调栈存储温度列表的下标,所以空间复杂度log(n),n为数组的长度。