二进制操作
选择排序
排序
动态规划
树
图
单调栈
两种理解方式
单调栈
给定一个数组,找到数组每个元素两边离他最近比他小的元素
单调栈(栈底到栈顶由小到大),栈顶元素出栈的时刻,就是栈顶元素信息生成的时刻。此时,他的右侧邻近小的元素就是加入栈的元素,左侧邻近小的元素就是栈中邻近的元素。
int[] arr = {3, 7, 8, 6, 4, 2, 6, 5};
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < n; i++) {
// 遍历到arr[i]就是要求left[i],即左侧邻近的比arr[i]小的元素
// 那如何求呢?简单来说如果我们有arr[0~i-1]就很好求出来了
// 而在遍历的过程中,实际上arr[0~i-1]是我们已经遍历过的
// 所以我们考虑一下,是否有处理一下已经遍历过的数组的方法
// 把已经遍历过的他们放到一个数据结构中,然后可以很方便的就能计算出left[i]
// 这个就是单调栈的作用
// (也就是说,单调栈是用来保存我们遍历过的数组的。只不过做了特殊的处理)
// 如何进行处理?单调栈的思想就是把“不好”的元素放在栈顶上
// 比如我们要求邻近最小,那大的值就是不好的元素,就让大元素尽可能在栈顶
while (!stack.empty() && arr[stack.peek()] >= arr[i]) stack.pop();
left[i] = stack.empty() ? -1 : stack.peek();
stack.push(i);
}
// 在这种处理办法中,要明确单调栈的作用
// 单调栈是用来记录已经遍历过的数组的
// 所以如果让求元素右侧邻近比它小的元素,那就要从后往前遍历
// 越接近栈底的元素是越“厉害”的元素,比如临近最小,栈底是最小的元素
int[] arr = {3, 7, 8, 4, 2, 6, 5};
Stack<Integer> stack = new Stack<>();