【单调栈】找到左右两边的最近小于元素

2023-11-06

基本概念

从一个问题引出单调栈的这个概念,给定一个数组,对于数组中的每一个元素,分别找到它左边和右边最近的小于它的元素

无重复数组

默认该数组中的元素是无重复的
我们可以维护一个栈,从栈的下方到上方,元素的大小从小到大.
对于数组中的每一个元素,
如果栈顶的元素小于当前的元素,那么直接将该元素push到栈中
如果栈顶的元素大于当前的元素,那么就要弹出栈顶的元素并直到栈顶的元素小于当前的元素为止.
同时对于那些被弹出的元素,
它们的右边最近的小于它的元素就是该元素,
左边最近的小于它的元素就是栈中它下面的元素

public static int[][] getNearLessNoRepeat(int[] arr){  
    int n=arr.length;  
    //res[i][0]保存的是左边的最小最近元素的下标
    //res[i][1]保存的是右边的最小最近元素的下标
    int[][] res=new int[n][2];  
    Stack<Integer> stack=new Stack<>();  
    for (int i = 0; i < n; i++) {  
        //如果该数字小,就执行退栈操作  
        while(!stack.isEmpty()&&arr[i]<arr[stack.peek()]){  
            int index=stack.pop();  
            int nextindex=stack.isEmpty()?-1:stack.peek();  
            res[index][0]=nextindex;  //栈中的下一个
            res[index][1]=i;  //该数组元素arr[i]
        }  
        //不然,直接进栈  
        stack.push(arr[i]);  
    }  
    //如果栈中还有剩余
    while (!stack.isEmpty()){  
        int index=stack.pop();  
        int nextindex=stack.isEmpty()?-1:stack.peek();  
        res[index][0]=nextindex;  
        res[index][1]=-1;  
    }  
    return res;  
}

有重复数组

上面是没有重复数组的情况,对于那些有重复数组的来说,分析方法是一样的,只是栈中原来存放的是数字,现在存放的是链表,链表中存放的都是相同的元素

如果当前数组元素小于栈顶的元素,还是要执行退栈操作直到当前数组元素大于栈顶的元素为止.
同时我们还要记录被退栈的那些元素的,左边右边的临近最小值,右边临近最小值就是该数组元素,左边临近最小值就是它的下方的链表的最尾部元素
如果当前数组元素等于栈顶的元素,那么直接将该元素加入到该栈顶元素的链表的尾部
如果当前数组元素大于栈顶的元素,那么构造出一个链表,将该元素加入到链表中,然后将链表放入栈中

public static int[][] getNearLessRepeat(int[] arr){  
    int n=arr.length;  
    int[][] res=new int[n][2];  
    Stack<List<Integer>> stack=new Stack<>();  
    for (int i = 0; i < n; i++) {  
        //如果该数字小,就执行退栈操作  
        while(!stack.isEmpty()&&arr[i]<arr[stack.peek().get(0)]){  
            List<Integer> list=stack.pop();  
            int nextindex=stack.isEmpty()?-1:stack.peek().get(stack.peek().size()-1);  
            for (Integer x:list){  
                res[x][0]=nextindex;  
                res[x][1]=i;  
            }  
        }  
        //不然,直接进栈  
        if(!stack.isEmpty()&&arr[i]==arr[stack.peek().get(0)]){  
            stack.peek().add(arr[i]);  
        }else{  
            List<Integer> list=new LinkedList<>();  
            list.add(arr[i]);  
            stack.push(list);  
        }  
    }  
    //栈中其余剩余的元素  
    while (!stack.isEmpty()){  
        List<Integer> list=stack.pop();  
        int nextindex=stack.isEmpty()?-1:stack.peek().get(stack.peek().size()-1);  
        for (Integer x:list){  
            res[x][0]=nextindex;  
            res[x][1]=-1;  
        }  
    }  
    return res;  
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【单调栈】找到左右两边的最近小于元素 的相关文章

随机推荐

  • Web网络安全-----红蓝攻防之信息收集(web、安卓...)

    系列文章目录 Web网络安全 Log4j高危漏洞原理及修复 文章目录 系列文章目录 前言 一 为什么要做信息收集 蓝队 红队 红蓝对抗 无疑是一场信息对抗大赛 二 空间搜索引擎类 1 FOFA https fofa info 2 鹰图 奇安
  • 九、Redis Shell

    Redis提供了redis cli redis server redis benchmark等Shell工具 它们虽然比较简单 但是麻雀虽小五脏俱全 有时可以很巧妙地解决一些问题 一 redis cli详解 第一章曾介绍过redis cli
  • Ubuntu用tar命令来备份系统

    文章目录 备份系统 1 进入root用户 2 进入根目录 3 开始备份 命令格式 选项 压缩文档的路径及名称 欲备份目录 恢复备份 参考 http nerotux tuxfamily org index php Articles TarCo
  • IDEA安装Gradle,解决IDEA与Gradle版本不匹配问题

    IDEA安装Gradle 解决IDEA与Gradle版本不匹配问题 文章目录 IDEA安装Gradle 解决IDEA与Gradle版本不匹配问题 一 检查IDEA适配的Gradle版本 二 下载Gradle并解压 三 配置环境变量 四 配置
  • SqlServer查询死锁进程,结束死锁进程

    查询死锁 select request session id spid OBJECT NAME resource associated entity id tableName from sys dm tran locks where res
  • 网卡相关

    如何查看本机的网卡 操作步骤 1 win R 输入cmd 2 然后 输入命令 ipconfig all 然后按回车键 3 找到本地连接中的描述 如下
  • 5.38版本keil5MDK编译标准库工程问题解决

    1 首先 在keil官网下载安装keil5 ARM MDK 5 38版本 然后安装芯片资源包 Keil STM32F1xx DFP 2 4 0 关于芯片资源包的安装 由于选用的是STM32F1系列的芯片 可以安装资源包 Keil STM32
  • 面试官:烂大街的 Spring 循环依赖问题你都不会,我怎么敢录用你

    在关于Spring的面试中 我们经常会被问到一个问题 Spring是如何解决循环依赖的问题的 这个问题算是关于Spring的一个高频面试题 因为如果不刻意研读 相信即使读过源码 面试者也不一定能够一下子思考出个中奥秘 本文主要针对这个问题
  • 电脑外接显示屏导致屏幕翻转不回来解决办法

    电脑外接显示屏导致屏幕翻转不回来解决办法 一条命令解决 xrandr的通常用法 一条命令解决 xrandr o normal xrandr的通常用法 xrandr o left 向左旋转90度 xrandr o right 向右旋转90度
  • Linux安装、查看、卸载软件、更换yum源

    Linux安装 查看 卸载软件 更换yum源 1 知识点 1 Linux安装软件有那些方式 2 Linux各种安装方式如何安装 更新软件 3 如何查看软件包是否安装 如何卸载安装过的软件包 4 Linux如何更换国内yum仓库源 2 实现
  • redis集群部署

    目录 简介 开启多实例 1 复制一份 redis conf 2 修改一下conf文件 3 复制配置文件修改端口 4 启用多实例 简介 本地redis集群是基于两台服务器 每台服务器分别运行三个实例 一共六个实例搭建集群 两台服务器为10 1
  • 使用Canal订阅binlog发送到RabbitMQ的删除补偿

    Canal k n l 译意为水道 管道 沟渠 主要用途是基于 MySQL 数据库增量日志解析 提供增量数据订阅和消费 工作原理 Canal的工作原理相对简单 就是把自己伪装成MySQL slave 模拟MySQL slave的交互协议向M
  • 微信小程序下载图片到本地

    downloadImg function e 触发函数 console log e currentTarget dataset url wx downloadFile url e currentTarget dataset url 需要下载
  • 性能测试 —— 什么是全链路压测?

    随着互联网技术的发展和普及 越来越多的互联网公司开始重视性能压测 并将其纳入软件开发和测试的流程中 阿里巴巴在2014 年双11 大促活动保障背景下提出了全链路压测技术 能更好的保障系统可用性和稳定性 什么是全链路压测 全链路压测是一种全面
  • 4.7 期货每日早盘操作建议

    期货期权日评 静待反抽 PMI数据显示国内疫情基本控制后复工已较明显 经济数据将在二季度逐步改善 同时近期高层在贷款 汽车消费方面政策频出 有望支持实体经济复苏 当前A股已处于低位 期指继续做空的风险收益比在下降 因此建议可在股指期权上轻仓
  • Failed to execute ‘addColorStop‘ on ‘CanvasGradient‘: The value provided (‘undefined‘) could not be

    在echarts使用属性visualMap对折线图进行区间的变色设置 结果写完直接报错 Uncaught DOMException Failed to execute addColorStop on CanvasGradient The v
  • springboottest注解

    SpringBoot test 好习惯要坚持下去 CSDN博客 springboot test springboot使用 SpringBootTest注解进行单元测试 灰太狼 CSDN博客 springboot test
  • 如何为模型不同层设置不同的学习率?

    在模型调参中常用的一种方法是针对不同层设置不同的学习率 以此避免因难易程度不一致引起的过拟合等问题 一 模型举例 class Model nn Module def init self input size hidden size outp
  • 【cfengDB】自己实现数据库第0节 ---整体介绍及事务管理层实现

    LearnProj 内容管理 MySQL系统结构 一条SQL执行流程 cfengDB整体结构 事务管理TM模块 TID文件规则定义 文件读写 NIO RandomAccessFile FileChannel ByteBuffer 接口实现
  • 【单调栈】找到左右两边的最近小于元素

    基本概念 从一个问题引出单调栈的这个概念 给定一个数组 对于数组中的每一个元素 分别找到它左边和右边最近的小于它的元素 无重复数组 默认该数组中的元素是无重复的 我们可以维护一个栈 从栈的下方到上方 元素的大小从小到大 对于数组中的每一个元