[LeetCode] 739. Daily Temperatures(每日温度)
-
Difficulty: Medium
-
Related Topics: Hash Table, Stack
Description
Given a list of daily temperatures T
, return a list such that, for each day in the input, tells you how many days you would have to wait until a warmer temperature. If there is no future day for which this is possible, put 0
instead.
给定一个每日温度列表 T
,返回一个列表,对于每一天的温度,能告诉你到下一个更温暖的温度还需等多少天。如果等不到这一天,则返回 0
。
For example, given the list of temperatures T = [73, 74, 75, 71, 69, 72, 76, 73]
, your output should be [1, 1, 4, 2, 1, 1, 0, 0]
.
例如,给定输入 T = [73, 74, 75, 71, 69, 72, 76, 73]
,你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]
。
Note
The length of temperatures
will be in the range [1, 30000]
. Each temperature will be an integer in the range [30, 100]
.
temperature
的长度在 [1, 300000]
。每一天的温度的范围在 [30, 100]
。(译者注:这一定不是在地球上的温度,或者用的是华氏温标?🌚)
Hints
- If the temperature is say, 70 today, then in the future a warmer temperature must be either 71, 72, 73, ..., 99, or 100. We would remember when all of them occur next.
如果今日的温度是 70,那么未来几日,更温暖的温度一定是从 71 到 100。我们可以在其下一次出现的时候记录下来。
Solution
这题一给出来,我的第一想法是“单调栈”这个数据结构。不过单调栈 Emmmm……我不会呀,遂求助于 Bing,查找的结果证明我的直觉是正确的。以下为单调栈的相关资料(摘抄于特殊数据结构:单调栈 - labuladong 的算法小抄)
单调栈实际上就是栈,只是利用了一些巧妙的逻辑,使得每次新元素入栈后,栈内的元素都保持有序(单调递增或单调递减)。
听起来有点像堆(heap)?不是的,单调栈用途不太广泛,只处理一种典型的问题,叫做 Next Greater Element。
…………
给你一个数组,返回一个等长的数组,对应索引存储着下一个更大元素,如果没有更大的元素,就存 -1。
…………
这个问题可以这样抽象思考:把数组的元素想象成并列站立的人,元素大小想象成人的身高。这些人面对你站成一列,如何求元素「2」的 Next Greater Number 呢?很简单,如果能够看到元素「2」,那么他后面可见的第一个人就是「2」的 Next Greater Number,因为比「2」小的元素身高不够,都被「2」挡住了,第一个露出来的就是答案。)
这个情景很好理解吧?带着这个抽象的情景,先来看下代码。
vector<int> nextGreaterElement(vector<int>& nums) { vector<int> res(nums.size()); // 存放答案的数组 stack<int> s; // 倒着往栈里放 for (int i = nums.size() - 1; i >= 0; i--) { // 判定个子高矮 while (!s.empty() && s.top() <= nums[i]) { // 矮个起开,反正也被挡着了。。。 s.pop(); } // nums[i] 身后的 next great number res[i] = s.empty() ? -1 : s.top(); // s.push(nums[i]); } return res; }
这就是单调队列解决问题的模板。for 循环要从后往前扫描元素,因为我们借助的是栈的结构,倒着入栈,其实是正着出栈。while 循环是把两个「个子高」元素之间的元素排除,因为他们的存在没有意义,前面挡着个「更高」的元素,所以他们不可能被作为后续进来的元素的 Next Great Number 了。
对单调栈的介绍到此为止。回到这个问题本身,上面的资料中本身已经给了单调栈的模板代码了,大部分都能直接套用进去。有两点需要变动一下:
-
单调栈里存放的是元素的下标值而非元素本身。
-
最后的结果里存的不是元素下标,而是两元素下标间的差值。
最后得到的代码如下:
import java.util.*
class Solution {
fun dailyTemperatures(T: IntArray): IntArray {
val stack = ArrayDeque<Int>()
val result = IntArray(T.size)
for (i in T.indices.reversed()) {
while (stack.isNotEmpty() && T[stack.peek()] <= T[i]) {
stack.pop()
}
result[i] = if (stack.isEmpty()) 0 else stack.peek() - i
stack.push(i)
}
return result
}
}
参考文献
- labudadong, 特殊数据结构:单调栈, https://labuladong.gitbook.io/algo/shu-ju-jie-gou-xi-lie/dan-tiao-zhan#wen-ti-bian-xing