【算法基础】2.1栈和队列(单调栈和单调队列)

news2024/11/26 4:12:35

文章目录

  • 例题
    • 3302. 表达式求值(栈的应用)😭😭😭😭😭
    • 830. 单调栈
      • 知识点
      • 解法
    • 154. 滑动窗口 (单调队列)
      • 知识点
      • 解法
  • 相关链接 & 相关题目

例题

3302. 表达式求值(栈的应用)😭😭😭😭😭

https://www.acwing.com/activity/content/problem/content/3648/
在这里插入图片描述

import java.util.*;

public class Main {
    // 存储数字的栈
    static Deque<Integer> numStk = new LinkedList<>();
    // 存储运算符号的栈
    static Deque<Character> opStk = new LinkedList<>();

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        // 各个运算符的优先级字典
        Map<Character, Integer> pr = Map.of('+', 1, '-', 1, '*', 2, '/', 2);
        for (int i = 0; i < s.length(); ++i) {
            char ch = s.charAt(i);
            // 如果是数字,直接放入栈里
            if (Character.isDigit(ch)) {
                int x = 0, j = i;
                while (j < s.length() && Character.isDigit(s.charAt(j))) {
                    x = x * 10 + (s.charAt(j) - '0');
                    ++j;
                }
                i = j - 1;
                numStk.push(x);
            } else if (ch == '(') opStk.push(ch);   // 左括号直接放入栈里
            else if (ch == ')') {                   // 出现右括号,一直计算到出现左括号
                while (opStk.peek() != '(') eval();
                opStk.pop();    // 把'('弹出来
            } else {            // 是运算符号,检查和上个运算符号之间的优先级关系如何,先算优先级大的
                while (!opStk.isEmpty() && opStk.peek() != '(' && pr.get(opStk.peek()) >= pr.get(ch)) eval();
                opStk.push(ch);
            }
        }
        while (!opStk.isEmpty()) eval();    // 把剩下的运算符都计算了
        System.out.println(numStk.peek());
    }

    static void eval() {
        // 取出两个数字和一个运算符进行运算
        int b = numStk.pop(), a = numStk.pop();
        char ch = opStk.pop();
        int x;
        if (ch == '+') x = a + b;
        else if (ch == '-') x = a - b;
        else if (ch == '*') x = a * b;
        else x = a / b;
        numStk.push(x);
    }
}

这题思路有难度,代码也很长。

使用栈来解决这个问题。


  • 遇到数字时,直接将数字放入栈中。
  • 遇到 ( 时,也直接放入栈中。
  • 遇到 ) 时,进行计算知道栈顶是 ( 。
  • 遇到运算符时,和当前在栈顶的运算符进行比较,先计算优先级高的运算符。

830. 单调栈

https://www.acwing.com/activity/content/problem/content/867/

在这里插入图片描述

知识点

单调栈 可以用来求取 数组中每一个元素 左右两边 第一个比它大或者第一个比它小的位置在哪里

解法

为了求每个数字左边第一个比它小的数字,需要使用一个单调栈。

这个单调栈从栈底到栈顶是单调递减的。

当枚举到一个元素时,从栈顶开始检查,如果栈顶的元素比当前元素小,那就找到了当前元素左边第一个更小的元素;
如果栈顶的元素 >= 当前的元素,那么就将其弹出栈。

如果栈是空的,说明左侧没有比当前元素更小的元素了。

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            int x = scanner.nextInt();
            while (!stk.isEmpty() && x <= stk.peek()) stk.pop();
            if (!stk.isEmpty()) System.out.print(stk.peek() + " ");
            else System.out.print("-1 ");
            stk.push(x);
        }
    }
}

154. 滑动窗口 (单调队列)

https://www.acwing.com/activity/content/problem/content/868/
在这里插入图片描述

知识点

单调队列常常用来维护一个窗口中当前的最大值或者最小值。

注意单调队列要使用 双端队列 来实现。

解法

使用两个双端队列分别维护当前窗口中的最大值和最小值。

和单调栈类似,每次枚举到一个新的元素时,将该元素一直与队列中的最后一个元素相比较,保持队列的单调性。

每个窗口的最大值和最小值就是队列队首的元素。

记得要及时移除窗口之外的元素。

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        Scanner sin = new Scanner(new BufferedInputStream(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        int n = sin.nextInt(), k = sin.nextInt();
        int[] a = new int[n], max = new int[n - k + 1], min = new int[n - k + 1];

        Deque<Integer> dqMax = new ArrayDeque<>(), dqMin = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            a[i] = sin.nextInt();
            while (!dqMax.isEmpty() && a[dqMax.peekLast()] <= a[i]) dqMax.pollLast();
            dqMax.offerLast(i);
            while (dqMax.peekFirst() + k <= i) dqMax.pollFirst();

            while (!dqMin.isEmpty() && a[dqMin.peekLast()] >= a[i]) dqMin.pollLast();
            dqMin.offerLast(i);
            while (dqMin.peekFirst() + k <= i) dqMin.pollFirst();

            if (i >= k - 1) {
                max[i - k + 1] = a[dqMax.peekFirst()];
                min[i - k + 1] = a[dqMin.peekFirst()];
            }
        }
        for (int i = 0; i < n - k + 1; ++i) bw.write(min[i] + " ");
        bw.write("\n");
        for (int i = 0; i < n - k + 1; ++i) bw.write(max[i] + " ");
        bw.flush();
        sin.close();
        bw.close();
    }
}

相关链接 & 相关题目

碰撞类问题是栈的经典应用场景:【算法】行星碰撞&机器人碰撞(栈的使用)
贡献法经常需要使用单调栈来找到左右两端的边界:【算法】贡献法相关题目练习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/754861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在进行自动化测试,遇到验证码的问题,怎么办?

1.找开发去掉验证码或者使用万能验证码 2.使用OCR自动识别 使用OCR自动化识别&#xff0c;一般识别率不是太高&#xff0c;处理一般简单验证码还是没问题 这里使用的是Tesseract-OCR,下载地址&#xff1a;https://github.com/A9T9/Free-Ocr-Windows-Desktop/releases 怎么使…

linux centos7 静默安装 oracle 11g,【亲测有效】,包含远程连接、提供安装包

Centos7 安装oracle11g 环境准备 操作系统 centos7 oracle版本 oracle11g 终端软件 MobaXterm 192.168.46.61 oracleMaster 安装包 网盘地址 一、安装前准备 1、关闭selinux [rootoracleMaster ~]# vim /etc/selinux/config修改 SELINUX 为 disabled # This file controls …

网络安全(黑客技术)自学

引言 ✈️网络安全&#xff0c;顾名思义&#xff0c;无安全&#xff0c;不网络。现如今&#xff0c;安全行业飞速发展&#xff0c;我们呼吁专业化的 就职人员 与 大学生 &#xff0c;而你&#xff0c;认为自己有资格当黑客吗&#xff1f; ✒️本文面向所有信息安全领域的初学者…

希尔排序

希尔排序 排序步骤 1、分组&#xff0c;以任意长度进行分组&#xff08;这个长度我们称作增量gap&#xff09;&#xff1b;通常以总长度的一半这个数为依据进行分组&#xff0c;每间隔 gap 个数即为一组 2、组内排序&#xff1b;组内使用插入排序法进行排序 3、重新设置间隔…

Wi-Fi 相关概念

Wi-Fi 相关概念 802.11 Wi-Fi 标准及其含义频宽 和 带宽 的概念20MHz与40MHz的区别2.4G 频段2.4G的频道编号和中心频率 5G WiFi 频段中国开放的的5G WiFi频段&#xff1a;5G的频道编号和中心频率&#xff1a; 802.11历史进程一、802.11重要发展二、802.11协议族 参考 802.11 Wi…

阿里云 OSS 静态网站托管

本文节选自我的博客&#xff1a;阿里云 OSS 静态网站托管 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是MilesChen&#xff0c;偏前端的全栈开发者。&#x1f4dd; CSDN主页&#xff1a;爱吃糖的猫&#x1f525;&#x1f4e3; 我的博客&#xff1a;爱吃糖的猫&…

云计算的学习(六)

六、云计算的发展趋势 1.云计算相关领域介绍 1.1物联网 物联网来源于互联网&#xff0c;是万物互联的结果&#xff0c;是人和物、物和物之间产生通信和交互。 物联网主要技术&#xff1a; RFID技术&#xff08;射频识别技术&#xff09;传感器技术嵌入式系统技术 1.2大数据…

SpringBoot+actuator和admin-UI实现监控中心

使用SpringBoot很久了&#xff0c;但是很少使用到SpringBoot的查看和监控&#xff0c;将来八成也不会用到&#xff0c;万一有机会用到呢&#xff1f;所以记录一下以前学习SpringBootactuator和adminUI实现监控中心的方式 Springboot的版本2.0.x <parent><groupId>…

在Linux下做性能分析2:ftrace

介绍 在我们进一步介绍更多模型分析技巧前&#xff0c;我们先要对基本工具有一些了解。这一篇先介绍ftrace的基本用法。 ftrace在内核的Documentation目录下已经有文档了&#xff0c;我这里不是要对那个文档进行翻译&#xff0c;而是要说明这个工具的设计理念和使用策略。细节…

H3C-Cloud Lab实验-链路聚合实验

实验拓扑图&#xff1a; 实验需求&#xff1a; 1、按照图示配置PC3和PC4的IP地址 2、在SW1和SW2的两条直连链路上配置链路聚合&#xff0c;实现链路冗余&#xff0c;并可以增加传输带宽 3、SW1和SW2之间的直连链路要配置为Trunk类型&#xff0c;允许所有vlan通过 4、中断SW…

基于JavaSwing+Mysql的仓库销售管理系统

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88049275 JDK1.8 MySQL5.7 功能&#xff1a;管理员与员工两个角色登录&#xff0c;基础数据查找&#xff0c;仓库查找&#xff0c;增删改查仓库信息、商品等 源码数据库文件配置文件课程设…

java单元测试(调试)

文章目录 测试分类JUnit单元测试介绍引入本地JUnit.jar编写和运行Test单元测试方法设置执行JUnit用例时支持控制台输入10.6.6 定义test测试方法模板 测试分类 **黑盒测试&#xff1a;**不需要写代码&#xff0c;给输入值&#xff0c;看程序是否能够输出期望的值。 **白盒测试…

LangChain + ChatGLM2-6B 搭建个人专属知识库

之前教过大家利用 langchain ChatGLM-6B 实现个人专属知识库&#xff0c;非常简单易上手。最近&#xff0c;智谱 AI 研发团队又推出了 ChatGLM 系列的新模型 ChatGLM2-6B&#xff0c;是开源中英双语对话模型 ChatGLM-6B 的第二代版本&#xff0c;性能更强悍。 树先生之所以现…

GitUI汉化

1.下载汉化文件 下载地址 备用下载地址 https://files.cnblogs.com/files/chenghu/git-gui-zh-master.zip https://files.cnblogs.com/files/chenghu/git-gui-zh-master.zip 2.找到git安装路径 C:\Program Files\Git\mingw64\share\git-gui\lib 3.解压出1下载的文件 复制粘…

配置无线网卡AP模式为wifi热点

1、判断网卡是否支持AP 不管是自带无线网卡、还是外接的usb无线网卡&#xff0c;要先配置为AP热点模式。需要看检查是否支持AP模式。 例如&#xff0c;这里插入 rtl8811c 的双频usb无线网卡&#xff0c;iwconfig查看网卡信息 nvidianvidia-desktop:~$ iwconfig wlan0 un…

数据结构——各种常见算法的实现方法和思路

文章目录 常见的排序算法类型复杂度和稳定性 1.冒泡排序2.直接插入排序3.希尔排序4.简单选择排序方法1&#xff1a;双向遍历选择排序方法2&#xff1a;单向遍历选择排序 5.归并排序方法1&#xff1a;递归方法2&#xff1a;非递归 6.快速排序方法1&#xff1a;随机取keyi方法2&a…

GD32F303 DAM串口接收

1.设置串口 串口配置比较常规&#xff0c;我只应用的空闲中断。 2.DMA设置 我设置的DMA是串口接收到数据后保存到数组里&#xff0c;数组满了以后会自动从头开始&#xff0c;并且会进入一次DMA中断。

Jenkins+Robot 接口自动化测试

目录 前言&#xff1a; 设计目标 项目说明 目录结构 配置 jenkins 1.安装插件 2.配置项目 前言&#xff1a; JenkinsRobot是一种常见的接口自动化测试方案&#xff0c;可以实现自动化的接口测试和持续集成。Jenkins是一个流行的持续集成工具&#xff0c;而Robot Framew…

代码随想录day3 | 203.移除链表元素 707.设计链表 206.反转链表

文章目录 一、移除链表元素的思想两种方法 二、203.移除链表元素三、707.设计链表四、206.反转链表 一、移除链表元素的思想 直接让前一个节点指向后一个节点即可 两种方法 第一种&#xff1a;直接删除 第二种&#xff1a;头删的时候&#xff0c;直接headhead->next 其实…

JAVA数据结构、集合操作及常用API_C++开发转JAVA

文章目录 零、引言一、JAVA数据结构基础1.0 数据类型概述1.1 基本数据类型 零、引言一、JAVA数据结构基础1.0 数据类型概述1.1 基本数据类型1.2 包装类1.3 基本类型和包装类型的区别1.4 包装类型的缓存机制1.5 equals() 和 1.6 自动装箱拆箱1.7 浮点数精度丢失1.8 数值、字符转…