题目
思路
这道题是关于寻找每日温度之后何时会出现更高温度的问题。
首先,我会分析题目的本质:对于温度数组中的每个元素,我们需要找到它右边第一个更大的元素,并计算它们之间的距离。这很符合单调栈的应用场景。
我的解题思路是:
- 创建一个结果数组,初始化为全0
- 维护一个单调递减栈,存储温度的索引(不是温度值本身)
- 从左到右遍历温度数组:
- 当当前温度高于栈顶索引对应的温度时,说明找到了栈顶元素的下一个更高温度
- 计算两者的索引差,更新结果数组
- 不断弹出栈顶并更新,直到栈为空或栈顶温度大于等于当前温度
- 将当前索引压入栈
示例 `temperatures = [73,74,75,71,69,72,76,73]` 一步步演示单调栈的处理过程:
- 初始化:
-
结果数组 `answer = [0,0,0,0,0,0,0,0]`
-
空栈 `stack = []`
- 遍历温度数组:
-
i=0,温度=73:
-
栈为空,直接压入 stack = [0]
-
i=1,温度=74:
-
74 > 73,栈顶元素0对应的温度比当前温度小
-
弹出栈顶0,计算 answer[0] = 1-0 = 1
-
stack = [1]
-
i=2,温度=75:
-
75 > 74,栈顶元素1对应的温度比当前温度小
-
弹出栈顶1,计算 answer[1] = 2-1 = 1
-
stack = [2]
-
i=3,温度=71:
-
71 < 75,直接压入
-
stack = [2,3]
-
i=4,温度=69:
-
69 < 71,直接压入
-
stack = [2,3,4]
-
i=5,温度=72:
-
72 > 69,弹出栈顶4,计算 answer[4] = 5-4 = 1
-
72 > 71,弹出栈顶3,计算 answer[3] = 5-3 = 2
-
72 < 75,压入5
-
stack = [2,5]
-
i=6,温度=76:
-
76 > 72,弹出栈顶5,计算 answer[5] = 6-5 = 1
-
76 > 75,弹出栈顶2,计算 answer[2] = 6-2 = 4
-
stack = [6]
-
i=7,温度=73:
-
73 < 76,直接压入
-
stack = [6,7]
- 遍历结束,最终结果:
- answer = [1,1,4,2,1,1,0,0]
关键点是:
-
我们始终保持栈中温度是单调递减的
-
每当遇到更高的温度,我们就找到了之前较低温度的"下一个更高温度"
-
栈中存的是索引而非温度值,这样可以方便计算天数差值
-
最终栈中剩下的索引对应的温度,就是那些在其右侧没有更高温度的日子
时间复杂度是O(n),因为每个元素最多入栈出栈各一次;空间复杂度也是O(n),用于存储栈和结果数组。
读者可能出现的错误写法
cpp
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> st;
vector<int> answer(temperatures.size(),0);
if(int i =0;i<temperatures.size();i++)
{
if(st.size() && temperatures[i] > temperatures[st.top()])
{
answer[st.top()] = i-st.top();
st.pop();
}
st.push(i);
}
return answer;
}
};
只处理一个栈顶元素:代码中使用if而不是while,意味着每次迭代只会处理一个栈顶元素,然后直接入栈,这会导致:
- 当一个高温度出现时,无法处理栈中所有受影响的元素
- 栈不能保持单调性
正确写法
cpp
vector<int> dailyTemperatures(vector<int>& temperatures) {
int n = temperatures.size();
vector<int> answer(n, 0);
stack<int> st;
for (int i = 0; i < n; i++) {
while (!st.empty() && temperatures[i] > temperatures[st.top()]) {
int prevIdx = st.top();
st.pop();
answer[prevIdx] = i - prevIdx;
}
st.push(i);
}
return answer;
}