基础
单调栈分为单调递增,单调递减
- 递增栈:
- 栈内元素从栈底到栈顶递增。
- 用于寻找 下一个更小元素。
- 递减栈:
- 栈内元素从栈底到栈顶递减。
- 用于寻找 下一个更大元素。
👉 核心模式就是:
1 2 3 4 5 6 7
| for (...) { while (!stack.isEmpty() && 当前元素和栈顶元素满足某条件) { // 处理逻辑:清算旧账 stack.pop(); } stack.push(当前元素/下标); }
|
题目:找出每个元素多少index后会出现比他大的元素
思路:
- 维护一个单调递减栈,存的是index
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Solution { 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[stack.peek()] < temperatures[i]) { int curIndex = stack.pop(); res[curIndex] = i - curIndex; } stack.add(i); } return res; } }
|
时间复杂度:ON
空间复杂度:ON
思路:
- 本质上还是接雨水,理解两个点: 1. 面积等于高度 * 宽度,所以对于任何一个柱子,都要看看往左右两边伸展的最大宽度是多少,使用单调栈 2. 栈有两个语义,栈[-2] 是栈[-1]的左边界,出栈操作时,表示栈[-1] > 当前元素,这样就为栈顶元素确定了两个边界。
- 这里解释一下,range 为什么是 range = i - leftIndex - 1; i 即右边第一个比 h(mid) 小的柱子位置,而leftindex 即左边第一个比它小的柱子(这个值很容易,根据单调栈特性,我们就可以直接peek()出来)
- 那么当前mid柱子 可扩展的范围 也就是 最右 - 最左 - 1 这里的 - 1就是要把最右最左给排除掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Solution { public int largestRectangleArea(int[] heights) { int n = heights.length; int[] newHeights = new int[n+2]; newHeights[0] = 0; newHeights[newHeights.length - 1] = 0; System.arraycopy(heights, 0, newHeights, 1 , n);
Stack<Integer> s = new Stack(); s.add(0); int res = 0; for(int i = 0; i < newHeights.length; i++){ while(!s.isEmpty() && newHeights[i] < newHeights[s.peek()]){ int midIndex = s.pop(); if(s.isEmpty()){ break; } int leftIndex = s.peek(); int range = i - leftIndex - 1; res = Math.max(res, newHeights[midIndex] * range); } s.add(i); } return res; } }
|
思路:
- 先做84题,是它的父问题。就是把它切 m(martix.length )个 84题问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| class Solution { int res = 0; public int maximalRectangle(char[][] matrix) { int[][] t = new int[matrix.length][matrix[0].length + 2]; for(int i = 0; i < t.length; i++){ t[i][0] = 0; t[i][t[0].length - 1] = 0; } for(int i = 0; i < t.length; i++){ for(int j = 1; j < t[0].length - 1; j++){ if(matrix[i][j - 1] == '1'){ t[i][j] = 1; if(i > 0) t[i][j] += t[i - 1][j]; } else t[i][j] = 0; } }
for(int[] tt: t){ f1(tt); } return res; } public void f1(int []hegihts){ Stack<Integer> s = new Stack(); s.add(0); for(int i = 1; i < hegihts.length; i++){ while(!s.isEmpty() && hegihts[s.peek()] > hegihts[i]){ int midIndex = s.pop(); if(s.isEmpty()){ break; } int leftIndex = s.peek(); res = Math.max(res, hegihts[midIndex] * (i - leftIndex - 1)); } s.add(i); } } }
|