首先最直观的思路就是两层循环遍历寻找第一个比当前温度高的,时间复杂度为 O ( n 2 ) O(n^2) O(n2)
接下来介绍单调栈的两种思路:
单调栈就是用来解决求一个元素左/右第一个最大/小的元素
单调栈就是一个栈,只是我们需要维护使得栈的内部存储元素是有序的,例如一个栈从栈顶到栈底 15 30 60,此时再来元素40,就需要把15,30pop出再把40入栈以此维护栈的单调性。
单调栈的作用就是用来记录前面访问元素中遍历过的元素
1.从右往左遍历
就像是横看成岭侧成峰, 寻找比当前大的元素,就相当于一眼看过去能看到的高山,低矮的山是无法看见的,所以我们无需维护小的元素。
此时栈内部维护的是当前下标左侧的可能的高温的值,以30,50,40,50,,50,60,40为例,栈内40,60入栈时,由于40比60小,所以60的下一个高温不可能是40,无需维护。
最后记录答案 栈顶元素下标 - 当前元素下标
2.从左往右遍历
从左到右单调栈内维护的就不再是可能的高温了,而是还未寻找到下一个高温的元素下标,而我们遍历到比栈顶温度高的就要把栈顶元素出栈并记录答案 当前元素下标 - 栈顶元素下标
总结
我们可以发现,从左到右和从右到左是思考的方式是不一样的,单调栈内维护的内容也不同,从右到左,栈内维护下一次的高温,从左往右维护未寻找到下一次高温 ,是一个事物的两个方面。
时间复杂度 O ( n ) O(n) O(n)
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
stack<int> st;
int n = temperatures.size();
vector<int> ans(n);
//从左到右
/*for(int i = 0; i < n; i++)
{
int t = temperatures[i];
while(!st.empty() && t > temperatures[st.top()])
{
int j = st.top();
st.pop();
ans[j] = i - j;
}
st.push(i);
}
return ans;*/
//从右往左
for(int i = n - 1; i >= 0; i--)
{
int t = temperatures[i];
while(!st.empty() && t >= temperatures[st.top()])
{
st.pop();
}
if(!st.empty())
{
ans[i] = st.top() - i;
}
st.push(i);
}
return ans;
}
};