携手创作,共同成长!这是我参与「掘金日新计划 · 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]
分析
通过分析题目可知几个信息点
- 下一个更高的温度就是下一个比当前位置的数字大的值
- 不存在返回0
我们分析题意有2种解法
- 暴力循环即可,第一次循环外面的数组,第二次基于当前数,继续遍历查找下一个比当前大的值,本题既然是Medium,那么肯定不希望我们是用暴力解法。
- 单调栈解决,我们正常遍历每日的温度,并维护一个单调栈。(可以理解拿当前的值与栈内元素进行查找),又因为我们要算出升温日的天数,所以栈中存储下标。
- 栈是空的 或者 当前值小于栈顶,我们直接入栈。
- 如果栈是有值的,并且值大于栈顶元素,说明找到了下一个升温日,需要出栈,并且把天数计算出来,继续判断栈顶元素。
代码
暴力解法
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为数组的长度。