首页 > 其他分享 >单调队列

单调队列

时间:2023-01-07 19:34:08浏览次数:57  
标签:min 队列 max int new 单调 out

单调队列

前言

图床在 \(Github\) 中 ,如果访问不了 \(Github\) ,则图片无法加载

引入

原题链接:P1886 滑动窗口 /【模板】单调队列 - 洛谷

题意简述:有一个长度为 \(n\) 的数组,求其每 \(k\) 个连续的数中的最大值及最小值。

常规思路,对于每一段 \(i\sim i+k-1\) 的序列,逐个比较来找出最大值(和最小值),时间复杂度约为 \(O(n \times k)\)。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // n=7,k=4,a={1,3,6,2,5,1,7};
        int n = sc.nextInt(), k = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) {
            a[i] = sc.nextInt();
        }
        for (int i = 0; i + k - 1 < n; ++i) {
            int max = a[i], min = a[i];
            for (int j = 1; j < k; ++j) {
                max = Math.max(max, a[i + j]);
                min = Math.min(min, a[i + j]);
            }
            System.out.println(String.format("从%d开始的k个数中最大值为:%d,最小值为:%d", i, max, min));
        }
    }
}

很显然,这其中进行了大量重复工作,除了开头 \(k-1\) 个和结尾 \(k-1\) 个数之外,每个数都进行了 \(k\) 次比较,而题中 \(100\%\) 的数据为 \(n\leq 10^6\) ,当 \(k\) 稍大的情况下,显然会 \(TLE\)。

定义

顾名思义,单调队列的重点分为「单调」和「队列」。

  • 「单调」指的是元素的「规律」——递增(或递减)。

  • 「队列」指的是元素只能从队头和队尾进行操作(是一个双端队列)。

基本思想

维护一个双端队列(\(Deque\)),遍历序列,当且仅当一个元素可能为某个区间的最值时才保留他。

例题分析

以求连续的 \(k\) 个数的最大值为例。

若 \(n=7,k=4,arr=\{1,3,6,2,5,1,7\}\)。

1

import java.io.*;
import java.util.ArrayDeque;
import java.util.Deque;

public class Main {
    static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

    static PrintWriter out=new PrintWriter(System.out);

    static int get() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    public static void main(String[] args) throws IOException {
        final int n = get(), k = get();
        int[] a = new int[n];
        for (int i = 0; i < n; ++i) a[i] = get();
        Deque<Integer> min = new ArrayDeque<>(), max = new ArrayDeque<>();
        for (int i = 0; i < n; ++i) {
            //如果超出窗口范围
            if (!min.isEmpty() && i - min.peekFirst() + 1 > k) min.pollFirst();
            //如果不再可能成为最小值,则出队
            while (!min.isEmpty() && a[min.peekLast()] >= a[i]) min.pollLast();
            min.offerLast(i);
            //说明此时窗口内元素个数已经足够,此后每个队首元素均为对应窗口的最值
            if (i + 1 >= k) out.print(a[min.peekFirst()] + " ");
        }
        out.println();
        for (int i = 0; i < n; ++i) {
            //最大值同理
            if (!max.isEmpty() && i - max.peekFirst() + 1 > k) max.pollFirst();
            while (!max.isEmpty() && a[max.peekLast()] <= a[i]) max.pollLast();
            max.offerLast(i);
            if (i + 1 >= k) out.print(a[max.peekFirst()] + " ");
        }
        out.close();
    }
}

参考资料

单调队列 - OI Wiki

算法学习笔记(66): 单调队列 - Pecco - 知乎

标签:min,队列,max,int,new,单调,out
From: https://www.cnblogs.com/Cattle-Horse/p/17033321.html

相关文章

  • 栈和队列
    栈一般数组和链表两种实现方式栈:先进后出、尾入尾出classStack{private:int*data;//存放栈中的数据intmaxsize;//栈最大空间inttop;//栈顶pu......
  • 简单算法:优先队列
    典型题目题目传送门优先队列对于蒟蒻来说,堆之类的……实在是有点不好理解。所以我们今天只从表面上讲讲什么是优先队列,并且争取做到熟练的运用(知其然不知其所以然)就好......
  • 代码随想录算法训练营第10天 | 232. 用栈实现队列 225. 用队列实现栈
    232.用栈实现队列文章:代码随想录(programmercarl.com)思路:使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈一个输入栈,一个输出栈,这里要注意输入栈......
  • 算法刷题 Day 10 | 232.用栈实现队列 225. 用队列实现栈
    今日任务:理论基础用栈实现队列用队列实现栈理论基础了解一下栈与队列的内部实现机智,文中是以C++为例讲解的。文章讲解:https://programmercarl.com/%E6%A0%......
  • 代码随想录day10 LeetCode 232. 用栈实现队列 225. 用队列实现栈
     232.用栈实现队列https://leetcode.cn/problems/implement-queue-using-stacks/利用两个栈来实现队列,一个先存储进去的,一个存储IN栈倒出来的元素,这样就可以获取到队首......
  • Redis实现秒杀功能 lua脚本判断库存、判断一人一单、添加到stream队列、异步处理订单
    需求:新增秒杀商品-将秒杀商品的id和秒杀数量添加到秒杀表中数据库操作将秒杀信息保存到Redis中基于Lua脚本,判断秒杀库存、一人一单,决定用户是否有下单资格如果抢购......
  • 「贪心&优先队列」数列极差
    本题为12月30日22寒假集训每日一题题解题目来源:(未知)题面题目描述佳佳的老师在黑板上写了一个由n个正整数组成的数列,要求佳佳进行如下操作:每次擦去其中的两个数a和......
  • 单调队列优化的DP问题
    单调队列优化的DP问题概述单调队列就是通过排除求最值时候的冗余,从而是队列具有性质,可以方便求解问题。DP的两个阶段:朴素DP的基本原理——闫氏DP分析法对朴素DP进行......
  • RabbitMQ延时队列
    1.延时队列定时关单RabbitMQ:7.延迟队列https://www.cnblogs.com/yydscn/p/15208402.html......
  • 处理队列消息
    新入门skynet系列视频b站网址https://www.bilibili.com/video/BV19d4y1678X系列博客的大纲在工作线程中,服务队列的消息被不断的取出来处理,并处理。staticvoid*th......