• 滑动窗口的最大值


    题目链接:https://www.acwing.com/problem/content/75/

    参考链接:https://www.cnblogs.com/baccano-acmer/p/9997514.html

    单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的作用

    单调队列的舞台

    由于单调队列的队头每次一定最小值,故查询为O(1)。
    进队出队稍微复杂点:
    进队时,将进队的元素为e,从队尾往前扫描,直到找到一个不大于e的元素d,将e放在d之后,舍弃e之后的所有元素;如果没有找到这样一个d,则将e放在队头(此时队列里只有这一个元素)。保证队列是单调增加的。
    出队时,对于单调队列,只需判断队头是否已经超出滑动窗口范围,若超出,则从队头退队。
    分析单调队列的时间复杂度,每个元素最多入队1次、出队1次,且出入队都是O(1)的,因此这是一个总时间O(n)的算法。
    Java版本算法模板:
    import java.util.LinkedList;
    import java.util.Scanner;
    
    public class Main1 {
    	static class node{
    		int num;
    		int id;
    		public int getNum() {
    			return num;
    		}
    		public void setNum(int num) {
    			this.num = num;
    		}
    		public int getId() {
    			return id;
    		}
    		public void setId(int id) {
    			this.id = id;
    		}
    		public node(int num, int id) {
    			this.num = num;
    			this.id = id;
    		}
    		public node() {
    		}
    
    
    	}
    	public static void main(String[] args) {
    		LinkedList<node> q1=new LinkedList<node>();
    		LinkedList<node> q2=new LinkedList<node>();
    		Scanner sc=new Scanner(System.in);
    		int n=sc.nextInt();
    		int k=sc.nextInt();
    		int a[]=new int[n+2];
    		for (int i = 1; i <=n; i++) {
    			a[i]=sc.nextInt();
    		}
    		for(int i=1;i<=n+1;i++)
    		{
    			if(!q1.isEmpty())
    			{
    				if(q1.peek().id+k<i)
    					q1.removeLast();
    				if(i>=1+k)
    					System.out.print(q1.peek().num+"  ");
    			}
    			while(!q1.isEmpty()&&q1.peekLast().num>=a[i]&&i<=n)
    				q1.removeLast();
    			q1.add(new node(a[i],i));
    		}
    		System.out.println();
    		for(int i=1;i<=n+1;i++)
    		{
    			if(!q2.isEmpty())
    			{
    				if(q2.peek().id+k<i)//队列首的元素是否已经过期
    					q2.removeFirst();
    				if(i>=1+k)//至少滑动k个单位才需要输出
    					System.out.print(q2.peek().num+"  ");
    			}
    			while(!q2.isEmpty()&&q2.peekLast().num<=a[i]&&i<=n)
    				q2.removeLast();
    			q2.add(new node(a[i],i));
    		}
    
    	}
    
    }
    

    以上的算法模板分别是求滑动窗口的最小值和最大值。

    对于oj上的题目的算法应用是:

    class Solution {
        static class node{
    		int num;
    		int id;
    		public int getNum() {
    			return num;
    		}
    		public void setNum(int num) {
    			this.num = num;
    		}
    		public int getId() {
    			return id;
    		}
    		public void setId(int id) {
    			this.id = id;
    		}
    		public node(int num, int id) {
    			this.num = num;
    			this.id = id;
    		}
    		public node() {
    		}
    
    
    	}
        public int[] maxInWindows(int[] nums, int k) {
    		ArrayList<Integer> res=new ArrayList<Integer>();
    		LinkedList<node> q2=new LinkedList<node>();
    		int n=nums.length;
    		int a[]=new int[n+2];
    		for (int i = 1; i <=n; i++) {
    			a[i]=nums[i-1];
    		}
    		for(int i=1;i<=n+1;i++)
    		{
    			if(!q2.isEmpty())
    			{
    				if(q2.peek().id+k<i)//队列首的元素是否已经过期
    					q2.removeFirst();
    				if(i>=1+k)//至少滑动k个单位才需要输出
    					//System.out.print(q2.peek().num+"  ");
    					res.add(q2.peek().num);
    			}
    			while(!q2.isEmpty()&&q2.peekLast().num<=a[i]&&i<=n)
    				q2.removeLast();
    			q2.add(new node(a[i],i));
    		}
    		int arr[]=new int[res.size()];
    		for (int i = 0; i < arr.length; i++) {
    			arr[i]=res.get(i);
    		}
    		return arr;
    	}
    }
    

    单调队列一般是使用在动态规划中。

    加油啦!加油鸭,冲鸭!!!
  • 相关阅读:
    C# 代码中调用 Javascript 代码段以提高应用程序的配置灵活性(使用 Javascript .NET 与 Jint)
    非软件行业公司自建软件开发部门能力不强的原因分析
    编程经验点滴----巧妙解决 Oracle NClob 读写问题
    编程经验点滴----在 Oracle 数据库中保存空字符串
    这几天上海移动网络可以直接打开 Google Play 了
    品牌电脑硬盘损坏后,使用MediaCreationTool从微软官方下载正版Windows到USB做安装盘
    编程经验点滴----使用接口表保存可能并发的业务,然后顺序处理
    生产打印系统的一些汇总--商业合同方面
    生产打印系统的一些汇总--概要
    外观模式
  • 原文地址:https://www.cnblogs.com/clarencezzh/p/10568210.html
Copyright © 2020-2023  润新知