滑动窗口的最大值
题目链接: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;
}
}
单调队列一般是使用在动态规划中。
加油啦!加油鸭,冲鸭!!!

浙公网安备 33010602011771号