单调栈结构以及应用

单调栈结构

题目

给定一个不含有重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i] 小的位置。返回所有位置的相应信息。

题目变形

给定一个不含有重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i] 大的位置。返回所有位置的相应信息。

举例说明

arr = {3,4,1,5,6,2,7}
返回结果:
{
 {-1,2},// 其中-1表示不存在
 {0,2},
 {-1,-1},
 {2,5}.
 {3,5},
 {2,-1},
 {5,-1}
}

本题可以以时间复杂度为O(N^2)来进行实现,每个位置向左向右进行遍历,可以进行确定,但是如果想让时间复杂度做到O(N),就需要使用到单调结构。

单调栈的思路

准备一个栈,记为Stack,在栈中存放的元素是数组的位置,开始时栈为空。如果找到一个i位置左边和右边离i位置最近且值比a r r[i]小的位置,那么stack从栈底到栈顶的位置所代表的值是严格递增的。如果找到一个i位置左边和右边离i位置最近且值比a r r[i]大的位置,那么stack从栈底到栈顶的位置所代表的值是严格递减的。本题利用的结构是前者。

单调栈的操作核心

本题中单调栈的核心就在于从栈底到栈顶要求的顺序是严格递增的。

  • 栈为空时,遍历数组直接放入栈中。
  • 当栈不为空时,遍历数组的值要与栈中所存的位置数据对应的数值进行比较,如果符合遍历数组的值大于栈顶的值,则直接放入栈中。
  • 如果是小于的话。栈顶的元素要进行弹出的操作,并且要进行清算的。

清算的原则

  • 如果X位置 被弹出,在栈中位于X位置下面的位置,就是X位置左边离X位置最近且值比arr[i]小的位置。当前遍历到位置就是X位置右侧离X位置最近且值比arr[i]小的位置。
  • 遍历阶段结束,清算栈中剩下的位置:弹出X的位置,则X位置下面的位置就是左侧离X最近且值要比X位置对应的值要小的位置,右侧就是不存在的位置,即-1。

代码

import java.util.Stack;

public class Code_03_stack {
    //
    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++) {
            /**
             * 若当前位置元素小于栈顶元素,则一直弹出栈顶元素,直到不小于位置,
             */
            while (!stack.isEmpty() && arr[i] < stack.peek()){
                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 leftIndex = stack.isEmpty()?-1:stack.peek();
            res[popIndex][0] = leftIndex;
            res[popIndex][1] = -1;
        }
        return res;
    }
    
}

进阶题目

可能含有重复数的数组该如何使用单调栈呢?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值