https://leetcode.cn/problems/daily-temperatures/description/
经典单调栈,关键难点在于如何利用单调栈这个数据结构解题
题意要求向右找到第一个比当前大的元素,若是暴力则是O(n^2),但是依据暴力的这个思想
可以利用单调栈优化,因为求右边第一个比当前元素大的元素,等价于求当前元素是否是之前左边遍历过的第一次遇见的大值
因此使用容器存储之前遍历过的元素,每次遍历当前元素,都从容器中取出一一比较即可知道答案,若发现是大值,则容器中的元素就可以减少一个,不用再继续比较
若未发现大值,则当前遍历的元素也是需要等待寻找答案,因此加入容器
但是若是单纯使用一个普通容器存储,(当特殊情况,比如数据严格倒序)则与暴力没什么区别,由于是比较大值,使用有序的容器,比如单调栈
且单调递增,每次比较都和栈顶元素比较,栈顶元素是最小的,也是最容易得到答案的,而不需要像普通容器一样不断地去遍历整个容器,比如若当前遍历元素比容器中都要小
若使用普通容器,则需要O(n)来比较,但是若是单调栈则O(1)即可,这里就实现了暴力O(n^2)的优化
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
// 经典单调栈
// 核心思想就是及时去除无用数据,保证栈中数据有序
// 从左到右,栈中存放此前遍历过的元素下标,每遍历到一个元素,就与栈顶元素进行比较
// 由于栈中是单调不严格递增的(从栈出口往里的顺序),栈顶元素是最小的,每次就与栈顶元素比较即可
// 若遍历到的元素比栈顶元素大,则遇见了栈顶元素右边第一个比它大的值,记录答案,出栈,继续比较栈顶元素,直到小于栈顶元素为止
// 若比栈顶元素小,则未找到答案,则入栈即可
// 官方题解是这样解释的:由于单调栈满足从栈底到栈顶元素对应的温度递减,因此每次有元素进栈时,会将温度更低的元素全部移除,并更新出栈元素对应的等待天数,这样可以确保等待天数一定是最小的。
// 简而言之,就是维护一个单调栈,维护此前遍历过的状态,通过比较出栈得到答案
int[] res=new int[temperatures.length];
Deque<Integer> st = new ArrayDeque<>();
for(int i=0;i<temperatures.length;i++)
{
int t= temperatures[i];
while(!st.isEmpty() && t > temperatures[st.peek()])
{
// 若当前遍历元素大于栈顶元素,则意味着找到了答案,出栈继续比较
int top=st.pop();
res[top]=i-top;
}
// 直到元素小于栈顶或者没有元素,才入栈
st.push(i);
}
return res;
}
}
标签:容器,遍历,int,每日,元素,栈顶,739,leetcode,单调 From: https://www.cnblogs.com/lxl-233/p/18415373