力扣打卡:739. 每日温度
解题思路
每日学习:单调栈,给定的元素是数组,需要找到数组中的每个元素的左边或者右边的大值的位置,那么应该考虑使用单调栈
理解单调栈:
- 维护一个(单调)不递减的栈或者(单调)不递增的栈
- 以此题的(单调)栈尾到栈顶的顺序是单调递减的栈
- 即每次发现了比栈顶大的元素,那么就将栈顶的元素弹出,再次检查,直至新发现的元素小于最新栈顶,然后压入栈
- (之所以容易考虑错一些想法,是因为在想象时,就没有按照算法的要求来)
定义一个复制的 point
栈,用于记录坐标的变化,与原有的栈进行同步的压入和弹出
重点理解为什么要使用单调栈
-
单调栈的意义在于时间复杂度是O(n)内,将所有元素的左边或者右边的大值找到
-
可以想象,每次压入栈时,都是小于等于栈顶的元素,一直累加,同时一直同步坐标,直至发现一个元素大于栈顶
-
那么栈顶的元素弹出,而后新栈顶的元素与新元素进行比较,直至最新的栈顶小于新发现的元素,这样就可以将大值的距离求出来
代码
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
// 使用单调栈
// 单调栈的使用场景
// - 需要每个元素中找到左边或右边比自己大的或者小的元素的距离
Deque<Integer> stack = new ArrayDeque<>(); // 记录元素
Deque<Integer> point = new ArrayDeque<>(); // 记录坐标
int [] ans = new int[temperatures.length];
for(int i=0; i<temperatures.length; i++){
while(!stack.isEmpty() && stack.peek() < temperatures[i]){
stack.pop(); // 弹出已经使用的元素
int p = point.pop(); // 弹出记录的坐标
ans[p] = i-p; // 将记录的坐标进行标记
}
stack.push(temperatures[i]);
point.push(i);
}
return ans;
}
}