「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。
题目
请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替。
示例 1:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
示例 2:
输入: temperatures = [30,40,50,60]
输出: [1,1,1,0]
示例 3:
输入: temperatures = [30,60,90]
输出: [1,1,0]
提示:
1 <= temperatures.length <= 10^530 <= temperatures[i] <= 100
思考
这是一道有意思的题目,难度中等。
方法一是使用两层for循环暴力遍历所有情况。我们可以结合实例去理解这道题。不难看出,当数组的下一个元素大于当前元素时,返回值中对应的数字是1,而默认值是0。当数组的下一个元素小于等于当前元素时,继续遍历下一个元素。但是,这种解法的时间复杂度较高,可以看到我们的执行耗时只击败了14.17%的用户,内存消耗只击败了5.03%的用户...我们可以借助单调栈的方法去提升代码的执行效率。
我们可以新建一个单调栈,用于储存数组的下标。遍历数组时,我们把数组的下标存入栈中,然后判断当栈的长度>0且当前温度大于栈顶对应的温度时,对返回值赋值,并弹出栈顶索引(因为返回值已经赋值了)。描述比较抽象,举个例子,对于温度列表 [73,74,75,71,69,72,76,73],
当 i=0 时,将 0 进栈。
stack=[0(73)]
ans=[0,0,0,0,0,0,0,0]
当 i=1 时,由于 74 > 73,因此移除栈顶元素 0,将 1 进栈。
stack=[1(74)]
ans=[1,0,0,0,0,0,0,0]
当 i=2 时,由于 75 > 74,因此移除栈顶元素 1,将 2 进栈。
stack=[2(75)]
ans=[1,1,0,0,0,0,0,0]
当 i=3 时,由于 71 < 75,因此将 3 进栈。
stack=[2(75),3(71)]
ans=[1,1,0,0,0,0,0,0]
当 i=4 时,由于 69 < 71,因此将 4 进栈。
stack=[2(75),3(71),4(69)]
ans=[1,1,0,0,0,0,0,0]
当 i=5 时,由于 72 > 69 和 71,因此依次移除栈顶元素 4 和 3,将 5 进栈。
stack=[2(75),5(72)]
ans=[1,1,0,2,1,0,0,0]
当 i=6 时,由于 76 > 72 和 75,因此依次移除栈顶元素 5 和 2,将 6 进栈。
stack=[6(76)]
ans=[1,1,4,2,1,1,0,0]
当 i=7 时,由于 73 < 76,将 7 进栈。
stack=[6(76),7(73)]
ans=[1,1,4,2,1,1,0,0]
解答
方法一:暴力
var dailyTemperatures = function(temperatures) {
let res = [], size = temperatures.length
for (let i = 0; i < size; i++) {
for (let j = i + 1; j < size; j++) {
// 满足条件
if (temperatures[j] > temperatures[i]) {
res[i] = j - i
break
}
// 倒数第二个元素大于倒数第一个元素
if (j === size - 1) {
res[i] = 0
}
}
}
// 数组最后一个元素是0
res[size - 1] = 0
return res
}
// 执行用时:1400 ms, 在所有 JavaScript 提交中击败了14.17%的用户
// 内存消耗:62.9 MB, 在所有 JavaScript 提交中击败了5.03%的用户
复杂度分析
- 时间复杂度:O(n^2),其中 n 是温度列表的长度。
- 空间复杂度:O(1),其中 n 是温度列表的长度。除了存储答案的数组以外,我们只需要维护常量空间。
方法二:单调栈
var dailyTemperatures = function(temperatures) {
let stack = [] // 维护一个存储下标的单调栈
let res = [], size = temperatures.length
for (let i = 0; i < size; i++) {
// 初始化
res[i] = 0
// 栈不为空 && 当前天温度大于栈顶天温度
while (stack.length > 0 && temperatures[i] > temperatures[stack[stack.length - 1]]) {
let prevIndex = stack.pop()
res[prevIndex] = i - prevIndex
}
// 入栈
stack.push(i)
}
return res
}
复杂度分析
- 时间复杂度:O(n),其中 n 是温度列表的长度。
- 空间复杂度:O(n),其中 n 是温度列表的长度。需要维护一个单调栈存储温度列表中的下标。