单调栈
单调栈是一种特殊的栈结构,其内部元素始终保持单调递增或者单调递减的特性。
- 单调递增栈:栈内元素从栈底到栈顶是单调递增的。当新元素入栈时,若它小于栈顶元素,则直接入栈;若它大于栈顶元素,就需要不断弹出栈顶元素,直至满足单调递增的条件再入栈。
- 单调递减栈:栈内元素从栈底到栈顶是单调递减的。当新元素入栈时,若它大于栈顶元素,则直接入栈;若它小于栈顶元素,就需要不断弹出栈顶元素,直至满足单调递减的条件再入栈。
1.每日温度
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。
public class Daily_Temperatures {
public int[] dailyTemperatures2(int[] temperatures) {
int lens=temperatures.length;//获取温度数组 temperatures 的长度。
int []res=new int[lens];//创建一个长度为 lens 的数组,用于存储每个温度需要等待的天数,初始值都为 0。
Deque<Integer> stack=new LinkedList<>();//创建一个双端队列 Deque 作为栈,用于存储温度数组的索引。
for(int i=0;i<lens;i++){//从索引0开始遍历temperatures。
while(!stack.isEmpty()&&temperatures[i]>temperatures[stack.peek()]){//对于每个元素,如果栈不为空且当前温度大于栈顶元素对应的温度,则执行以下操作:弹出栈顶元素,并计算结果数组res中该元素对应的值。继续检查栈是否为空以及栈顶元素对应的温度是否小于当前温度,直到栈为空或栈顶元素对应的温度不小于当前温度。
res[stack.peek()]=i-stack.peek();//当前索引 i 对应的温度比栈顶元素对应的温度高,所以等待天数就是两者索引的差值。peek() 方法的作用是查看栈顶元素,却不把该元素从栈中移除。
stack.pop();//计算完等待天数后,将栈顶元素弹出,继续检查新的栈顶元素,直到栈为空或栈顶元素对应的温度不小于当前温度。
}
stack.push(i);//无论是否执行了 while 循环,都将当前索引 i 压入栈中。
}
return res;
}
}
temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
。
初始化:
-
数组长度:
lens = temperatures.length = 8
。 -
结果数组:
res = [0, 0, 0, 0, 0, 0, 0, 0]
(初始值为0)。 -
栈:
stack = []
(空栈)。
逐步执行:
我们将逐步遍历 temperatures
数组,并按照代码逻辑操作栈和结果数组。
第1天(索引 i = 0):
-
当前温度:
temperatures[0] = 73
。 -
栈为空,直接将索引0压入栈:
stack = [0]
。
第2天(索引 i = 1):
-
当前温度:
temperatures[1] = 74
。 -
栈不为空,且
74 > temperatures[stack.peek()] = temperatures[0] = 73
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为0。 -
计算等待天数:
res[0] = i - stack.peek() = 1 - 0 = 1
。 -
更新结果数组:
res = [1, 0, 0, 0, 0, 0, 0, 0]
。
-
-
将当前索引1压入栈:
stack = [1]
。
第3天(索引 i = 2):
-
当前温度:
temperatures[2] = 75
。 -
栈不为空,且
75 > temperatures[stack.peek()] = temperatures[1] = 74
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为1。 -
计算等待天数:
res[1] = i - stack.peek() = 2 - 1 = 1
。 -
更新结果数组:
res = [1, 1, 0, 0, 0, 0, 0, 0]
。
-
-
将当前索引2压入栈:
stack = [2]
。
第4天(索引 i = 3):
-
当前温度:
temperatures[3] = 71
。 -
栈不为空,但
71 < temperatures[stack.peek()] = temperatures[2] = 75
。 -
直接将当前索引3压入栈:
stack = [2, 3]
。
第5天(索引 i = 4):
-
当前温度:
temperatures[4] = 69
。 -
栈不为空,但
69 < temperatures[stack.peek()] = temperatures[3] = 71
。 -
直接将当前索引4压入栈:
stack = [2, 3, 4]
。
第6天(索引 i = 5):
-
当前温度:
temperatures[5] = 72
。 -
栈不为空,且
72 > temperatures[stack.peek()] = temperatures[4] = 69
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为4。 -
计算等待天数:
res[4] = i - stack.peek() = 5 - 4 = 1
。 -
更新结果数组:
res = [1, 1, 0, 0, 1, 0, 0, 0]
。
-
-
栈不为空,且
72 > temperatures[stack.peek()] = temperatures[3] = 71
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为3。 -
计算等待天数:
res[3] = i - stack.peek() = 5 - 3 = 2
。 -
更新结果数组:
res = [1, 1, 0, 2, 1, 0, 0, 0]
。
-
-
栈不为空,但
72 < temperatures[stack.peek()] = temperatures[2] = 75
。 -
将当前索引5压入栈:
stack = [2, 5]
。
第7天(索引 i = 6):
-
当前温度:
temperatures[6] = 76
。 -
栈不为空,且
76 > temperatures[stack.peek()] = temperatures[5] = 72
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为5。 -
计算等待天数:
res[5] = i - stack.peek() = 6 - 5 = 1
。 -
更新结果数组:
res = [1, 1, 0, 2, 1, 1, 0, 0]
。
-
-
栈不为空,且
76 > temperatures[stack.peek()] = temperatures[2] = 75
。-
弹出栈顶元素:
stack.pop()
,栈顶索引为2。 -
计算等待天数:
res[2] = i - stack.peek() = 6 - 2 = 4
。 -
更新结果数组:
res = [1, 1, 4, 2, 1, 1, 0, 0]
。
-
-
栈为空,将当前索引6压入栈:
stack = [6]
。
第8天(索引 i = 7):
-
当前温度:
temperatures[7] = 73
。 -
栈不为空,但
73 < temperatures[stack.peek()] = temperatures[6] = 76
。 -
将当前索引7压入栈:
stack = [6, 7]
。
最终结果:
-
遍历结束后,栈中剩余的索引对应的温度没有更高的温度,因此它们的结果值保持为0。
-
最终结果数组:
res = [1, 1, 4, 2, 1, 1, 0, 0]
。