1 定义
栈中数据呈现单调性的栈,叫做单调栈。
2 分类
(1)单调递增栈:从栈底到栈顶,元素从小到大的栈。
(2)单调递减栈:从栈底到栈顶,元素从大到小的栈。
3 解决问题
(1)单调递增栈:找出数组所有元素,下一个比它小的元素。
(2)单调递减栈:找出数组所有元素,下一个比它大的元素。
4 实际应用:找到数组元素下一个比它大的元素
示例1:输入:[2,1,5] ,输出:[5,5,0]
示例2:输入:[2,7,4,3,5],输出:[7,0,5,5,0]
解法一:暴力破解
遍历数组每个元素后面的元素,找出第一个比它大的元素。时间复杂度是 O(n^2)。
public static int[] nextLargerForce(int[] arr) {。 int[] res = new int[arr.length]; for (int i = 0; i < arr.length - 1; i++) { for (int j = i + 1; j < arr.length; j++) { if (arr[i] < arr[j]) { res[i] = arr[j]; break; } } } return res; }
解法二:单调递减栈
只遍历一遍数组就找到所有元素的目标元素,时间复杂度是O(n)。
思路:遍历数组元素依次入栈。如果当前元素小于/等于栈顶元素,当前元素直接入栈;否则栈顶元素出栈,并且确定了栈顶元素的目标元素就是当前元素。
注意:入栈的是数组下标,不是数组元素。
具体的代码实现如下:
public static int[] nextLargerStack(int[] arr) { Stack<Integer> stack = new Stack<>(); int[] res = new int[arr.length]; // 遍历一遍数组就可以了 for (int i = 0; i < arr.length; i++) { while (!stack.isEmpty() && arr[i] > arr[stack.peek()]) { int index = stack.pop(); res[index] = arr[i]; } stack.add(i); } return res; }
举例:
拿数组[2,7,4,3,5]为例
第一次循环:栈为空,arr[0]直接入栈;
第二次循环:arr[1]跟栈顶元素比较,大于栈顶元素,栈顶元素arr[0]出栈,arr[0]目标元素是arr[1];
栈为空,arr[1]入栈;
第三次循环:arr[2]跟栈顶元素比较,小于栈顶元素,arr[2]直接入栈;
第四次循环:arr[3]跟栈顶元素比较,小于栈顶元素,arr[3]直接入栈;
第五次循环:arr[4]跟栈顶元素比较,大于栈顶元素,栈顶元素arr[3]出栈,确定arr[3]目标元素是arr[4];
arr[4]跟栈顶元素比较,大于栈顶元素,栈顶元素arr[2]出栈,确定arr[2]目标元素是arr[4];
arr[4]跟栈顶元素比较,小于栈顶元素,arr[4]入栈。
5 类似题目
LeetCode1019:下一个比它大的元素。
LeetCode739:每日温度。
LeetCode84:柱状图中最大的矩形。
LeetCode42:接雨水。