价值:记录学习过程的思考,本身就是一场动态规划的前生,记忆化搜索。
单调栈:及时去掉无用数据,保证栈中数据有序。
Problem: LCR 038. 每日温度
思路
"数组"、"当前元素下一个 最大 "、 "当前元素下一个 最小"
暴力怎么做?
正向:从当前这个元素,往后枚举,找到大于当前的,得出结果,然后后移一位,每个结果的计算过程
是N,枚举N个,时间复杂度是 N*N
反向:从当前这个元素,往前枚举,找到 < 当前的"第一个",得出结果,但是要不要出栈呢,是不是无用数据?
不是,很有可能比如 2,1,3 这种情况,对于 2来说,当前栈顶不是无效的,1反而是无效的,因为1得到了结果,及时移走。
每次都从这个末尾算,直到有一个比他大的,说明他不是 从右到左,第一个最大的这个定义,这个时候才位置移动。 时间复杂度 N*N
[1,4,3,5,5,2,3,6]
正向枚举,
先放进去一个,对后边的枚举、判断
判断 当前元素 > 栈顶元素
如果无法得到结果,就入栈,否则得到结果后,就变成了无用数据,及时出栈
[1]
[4]
[4,3]
[5]
[5,5]
[5,5,2]
[5,5,3]
[6]
反向枚举,"栈不空"
先放进去一个,对后边的枚举、判断
判断 当前元素 < 栈顶元素 统统入栈,直到出现 当前元素大于栈顶,出栈
[6]
[6,3]
[6,3,2]
[6,5]
[6,5前]
[6,5,3]
[6,5,4]
[6,5,4,1]
Code
class Solution {
//L->R
// public int[] dailyTemperatures(int[] temperatures) {
// int n = temperatures.length;
// Deque<Integer> stack = new ArrayDeque<>();
// int [] ans = new int[n];
// for(int i = 0 ; i < n; i++){
// //对于每一个元素i来说,先入栈,找到结果就没用了,及时清除,否则入栈
// //这里用值显示下 入 :73 ,74>73?pop->ans : append 74 这个过程
// while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peekLast()]){
// int top_index = stack.pollLast();
// ans[top_index] = i - top_index;
// }
// stack.addLast(i);
// }
// return ans;
// }
// i : 0 1 2 3. 4. 5
// 栈 : 0 (74>73)--i~0走--nil--i~1 (75>74)--i~1走--nil--i~2. (71<75)--i~3. (69<71)--i~4 (72>71)--i~4走
// res: 1-0. 2-1 5-4
//R->L。单调小
public int[] dailyTemperatures(int[] temperatures) {
int n = temperatures.length;
Deque<Integer> stack = new ArrayDeque<>();
int [] ans = new int[n];
for(int i = n-1; i>=0; i--){
int curValue = temperatures[i];
while(!stack.isEmpty() && temperatures[stack.peekLast()] <= curValue){
//R->L枚举过程,不会再作为找答案有效判断,栈顶数据不会再用到了
stack.pollLast();
}
if(!stack.isEmpty()){
ans[i] = stack.peekLast() - i;
}
stack.addLast(i);
}
return ans;
}
}