问题
- 了解数组中的一个数,左边最近的比这个数大的数,和右边最近的比这个数大的数在哪
- 在一维数组中对每一个数找到第一个比自己小的元素。这类“在一维数组中找第一个满足某种条件的数”的场景就是典型的单调栈应用场景
单调栈
无重复数字
- 求某个数字附近最近的比他大的数字:
- 栈中放的内容都是链表,每个位置链表结点存放index
- 弹出的时候,右边最近比他大的数字是当前等待进栈的数字,左边最近的比他大的数字是栈中下面紧邻位置链表的最后一个位置
- 同样数字进栈的时候,将同样的数字对应的index串联在进栈位置链表的下一个位置
public static int[][] getNearLessNoRepeat(int[] arr) {
int[][] res = new int[arr.length][2];
// 只存位置!
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < arr.length; i++) { // 当遍历到i位置的数,arr[i]
while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
int j = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
res[j][0] = leftLessIndex;
res[j][1] = i;
}
stack.push(i);
}
while (!stack.isEmpty()) {
int j = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
res[j][0] = leftLessIndex;
res[j][1] = -1;
}
return res;
}
public static int[][] getNearLess(int[] arr) {
int[][] res = new int[arr.length][2];
Stack<List<Integer>> stack = new Stack<>();
for (int i = 0; i < arr.length; i++) { // i -> arr[i] 进栈
while (!stack.isEmpty() && arr[stack.peek().get(0)] > arr[i]) {
List<Integer> popIs = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);
for (Integer popi : popIs) {
res[popi][0] = leftLessIndex;
res[popi][1] = i;
}
}
if (!stack.isEmpty() && arr[stack.peek().get(0)] == arr[i]) {
stack.peek().add(Integer.valueOf(i));
} else {
ArrayList<Integer> list = new ArrayList<>();
list.add(i);
stack.push(list);
}
}
while (!stack.isEmpty()) {
List<Integer> popIs = stack.pop();
int leftLessIndex = stack.isEmpty() ? -1 : stack.peek().get(stack.peek().size() - 1);
for (Integer popi : popIs) {
res[popi][0] = leftLessIndex;
res[popi][1] = -1;
}
}
return res;
}
Leetcode 739.每日温度
单调栈解法
可以维护一个存储下标的单调栈,从栈底到栈顶的下标对应的温度列表中的温度依次递减。如果一个下标在单调栈里,则表示尚未找到下一次温度更高的下标。
正向遍历温度列表。对于温度列表中的每个元素
temperatures[i],如果栈为空,则直接将i进栈,如果栈不为空,则比较栈顶元素prevIndex对应的温度temperatures[prevIndex]和当前温度temperatures[i],如果temperatures[i]>temperatures[prevIndex],则将prevIndex移除,并将prevIndex对应的等待天数设为i - prevIndex,重复上述操作直到栈为空或者栈顶元素对应的温度小于等于当前温度,然后将 i 进栈。
class Solution { |
Leetcode 42. 接雨水
- 此题也是找一个从下到上单调递减的栈
class Solution {
public:
int trap(vector<int>& height) {
stack<int> s;
int retVal = 0;
for(int i = 0; i<height.size(); ++i)
{
if(!s.size())
{
s.push(i);
continue;
}
int tmp = s.top();
while(s.size() && height[i]>height[tmp])
{
s.pop();
if(s.size() == 0)break;
int w = i-s.top()-1;
int h = min(height[i], height[s.top()]) - height[tmp];
retVal+=w*h;
tmp = s.top();
}
s.push(i);
}
return retVal;
}
};Leetcode 84. 柱状图中最大的矩形
- 随后我们需要进行向左右两边扩展,使得扩展到的柱子的高度均不小于
h。换句话说,我们需要找到左右两侧最近的高度小于h的柱子,这样这两根柱子之间(不包括其本身)的所有柱子高度均不小于h,并且就是i能够扩展到的最远范围。
class Solution { |
Leetcode 155.最小栈
当一个元素要入栈时,我们取当前辅助栈的栈顶存储的最小值,与当前元素比较得出最小值,将这个最小值插入辅助栈中
当一个元素要出栈时,我们把辅助栈的栈顶元素也一并弹出
在任意一个时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中
class MinStack { |