题目
思路
本题需要用到单调栈的思想:
准备一个栈,从左往右遍历每个下标i
,检查栈顶元素j
代表的数arr[j]
是否小于arr[i]
-
如果小于,将栈顶元素
j
弹出,直到栈顶元素大于等于arr[i]
,或栈为空位置- 将栈顶元素
j
弹出时,位置j
代表的数需要等待的天数就为i - j
- 将栈顶元素
- 如果大于,则将下标
i
压入栈中,继续看下一个数
当遍历完成时,栈中剩下的数中,由于右边没有比这些数更大的数,因此需要等待的天数为0
我们来看为什么这样做正确:
- 结论:当
arr[i] > arr[j]
导致j
被弹出时时,i
一定是j
右边,第一个比j
大的数
- 证明:根据规则,每个数与将栈顶所有小于当前的数的数都弹出,然后把自己压入栈中,形成一个从大到小(从栈底到栈顶)的单调栈。那么如果
i
不是j
右边第一个比j
大的数,j
会在之前遇到第一个比j
大的数时就被弹出,而不会等到遇到i
时才被弹出
代码
public int[] dailyTemperatures(int[] temperatures) {
Stack<Integer> stack = new Stack<>();
int[] res = new int[temperatures.length];
for (int i = 0;i<temperatures.length;i++) {
while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) {
// 结算j
res[stack.peek()] = i - stack.peek();
// 弹出j
stack.pop();
}
// 将i压入栈中
stack.push(i);
}
return res;
}