1. 二进制操作
  2. 排序
  3. 动态规划
  4. 单调栈

二进制操作

选择排序

排序

动态规划

单调栈

两种理解方式

单调栈

给定一个数组,找到数组每个元素两边离他最近比他小的元素

单调栈(栈底到栈顶由小到大),栈顶元素出栈的时刻,就是栈顶元素信息生成的时刻。此时,他的右侧邻近小的元素就是加入栈的元素,左侧邻近小的元素就是栈中邻近的元素。

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<>();