04、单调栈是什么?

1、不考虑重复值 

思路分析:

1、准备一个栈结构,存放的是元素的下标,里面的元素是从小到大进行排序

2、依次遍历数组

当遍历到0位置的3时候,由于栈为空,直接入栈,此时栈中有3

当遍历到1位置的4时候,由于4比3大,直接入栈,此时栈中有3、4

当遍历到2位置的2时候,由于2比4小,此时4出栈,那么4左边比它小的是3,右边比它小的是2

然后2再去和3比较大小,由于2比3小,那么3出栈,那么3左边比它小的是无,右边比它小的是2

最后2入栈,此时栈中有2

当遍历到3位置的5时候,由于5比2大,直接入栈,此时栈中有2、5

当遍历到4位置的6时候,由于6比5大,直接入栈,此时栈中有2、5、6

当遍历到5位置的0时候,由于0比6小,那么6出栈,此时6左边比其小的是5,右边比其小的是0

此时栈中有2、5,然后0再去和5比较,那么5出栈,此时5左边比其小的是2,右边比其小的是0

此时栈中有2,然后0再去和2比较,那么2出栈,此时2左边比其小的是无,右边比其小的是0

最后0入栈,此时栈中有0

当遍历到6位置的1时候,由于1比0大,直接入栈,此时栈中有0、1

最后依次出栈

1 左边比其小的是0,右边比其小的是无

0 左边比其小的是无,右边比其小的也是无

//数组没有重复值的时候,解决方案如下:
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位置值,那么则弹出队列最后一个元素,处理数据
        while (!stack.isEmpty() && arr[stack.peek()] > arr[i]) {
            int popIndex = stack.pop();
            int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
            res[popIndex][0] = leftLessIndex;
            res[popIndex][1] = i;
        }
        stack.push(i);
    }
    //走到这一步,如果队列中还有元素,那么则依次弹出,右侧比其小的元素都没有
    while (!stack.isEmpty()) {
        int popIndex = stack.pop();
        int leftLessIndex = stack.isEmpty() ? -1 : stack.peek();
        res[popIndex][0] = leftLessIndex;
        res[popIndex][1] = -1;
    }
    return res;
}

 2、考虑重复值

思路分析(上面这个图里面数据是错误的,知道大概是这个意思就行):

1、准备一个栈,里面存放的是一个数组,数组里面存放的是元素小标,也是从小到大排序

2、当遍历到0位置的3时候,由于栈为空,直接入栈

当遍历到1位置的2时候,因为2比3小,那么3出栈,此时3左边比其小的是无,右边比其小的是2

2入栈,此时栈中有2

当遍历到2位置的3时候,由于3比2大,直接入栈

当遍历到3位置的4时候,由于4比3大,直接入参

当遍历到4位置的4时候,由于4和4相等,那么3和4位置的索引直接合并到一个集合中,入栈

。。。。。。

大致思路就是这样的了

 

//数组有重复值的时候,解决方案如下:
public static int[][] getNearLess(int[] arr) {
    int[][] res = new int[arr.length][2];
    // List<Integer> -> 放的是位置,同样值的东西,位置压在一起
    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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值