1. 题目
https://leetcode.cn/problems/daily-temperatures/
2. 解法
单调栈
- 单调栈是一种满足单调性的栈结构,也就是说,栈中的元素按照它们在栈内的位置,要么递增,要么递减。
- 单调栈可以在O(n)的时间复杂度内解决一些找到下一个更大或更小元素的问题,例如每日温度、股票价格跨度等。
- 单调栈也可以用于找到一维数组中每个元素的左右边界,例如计算直方图中的最大矩形面积、接雨水等。
解答思路如下:
- 创建一个栈,用来存储温度的索引。
- 创建一个结果数组,用来存储每天需要等待的天数。
- 从左到右遍历温度列表,对于每个温度,做以下操作:
- 如果栈为空,或者当前温度小于等于栈顶索引对应的温度,就将当前索引压入栈中,表示还没有找到更暖和的温度。
- 如果当前温度大于栈顶索引对应的温度,就弹出栈顶,并计算两个索引之间的距离,作为结果数组中对应位置的值,表示找到了更暖和的温度。
- 遍历结束后,栈中剩余的索引都没有更暖和的温度,所以结果数组中对应位置的值都是0。
public int[] dailyTemperatures(int[] temperatures) { int lenth = temperatures.length; int[] ans = new int[lenth]; Stack<Integer> stack = new Stack<>(); for (int i = 0; i < lenth; i++) { while (!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]) { int index = stack.pop(); ans[index] = i - index; } stack.push(i); } return ans; }
3. 总结
单调栈是一种特殊的栈结构,它的元素是按照严格的单调递增或者递减的顺序排列的。单调栈可以用来解决一些和数组中元素的大小关系相关的问题,比如找到数组中每个元素左边或者右边第一个比它大或者小的元素。
单调栈的原理是利用栈的先进后出的特性,维护一个单调的序列,每次遍历数组中的一个元素时,判断它和栈顶元素的大小关系,如果满足单调性,就直接入栈;如果不满足单调性,就不断出栈,直到栈为空或者满足单调性为止。这样可以保证栈中的元素始终是单调的,并且对于出栈的元素,可以找到它们左边或者右边第一个比它大或者小的元素。
单调栈的应用有很多,比如:
求解柱状图中最大的矩形面积。给定一个数组,表示柱状图中每个柱子的高度,求出其中能够组成的最大矩形面积。这个问题可以用单调递增栈来解决,对于每个柱子,找到它左边和右边第一个比它低的柱子,这样就可以确定它能够组成的最大矩形的宽度。具体算法可以参考。
求解温度变化天数。给定一个数组,表示每天的温度,求出每天需要等待多少天才能等到温度升高。这个问题可以用单调递减栈来解决,对于每天的温度,找到它右边第一个比它高的温度,这样就可以确定它需要等待的天数。具体算法可以参考。
求解下一个更大元素。给定两个数组,第一个数组是第二个数组的子集,求出第一个数组中每个元素在第二个数组中右边第一个比它大的元素。如果不存在,则返回-1。这个问题可以用单调递减栈来解决,对于第二个数组中每个元素,找到它右边第一个比它大的元素,并用一个哈希表记录下来。然后遍历第一个数组中每个元素,在哈希表中查找对应的结果。具体算法可以参考。