思路:
使用单调队列进行记录当前窗口的最大值或最小值 , q[tt]记录队列尾的元素 , q[hh] 记录队列头的元素
当记录最小值时:
1) 当新加入元素小于que[tt]时 , tt-- 直到找到小于新加入元素的值 或者 队列全部为空
2) 当新加入元素大于等于que[tt]时 ,tt++ 记录新加入元素的值 ,同时hh++,队列的最后一个元素出队。
当记录最大值时:过程与最小值相似
ps: BufferedReader 比 scanner快很多 输入数据大于10^6 时多使用bufferedreader
import java.util.*;
import java.io.IOException;
import java.io.*;
public class Main{
static int N = 1000006;
static int[] q = new int[N];
static int[] arr = new int[N];
public static void main(String[] args ) throws IOException{
BufferedReader br =new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
String[] f = br.readLine().split(" ");
int n = Integer.parseInt(f[0]);
int k = Integer.parseInt(f[1]);
String[] f2 = br.readLine().split(" ");
int hh = 0;
int tt = -1;
for(int i = 0 ; i < n ; ++i) arr[i] = Integer.parseInt(f2[i]);
// h作为滑动窗口的尾 , 记录最小值
for(int i = 0 ; i < n ; ++i){
if(tt >= hh && q[hh] < i - k + 1) hh++; // 当队尾已经超过窗口移动范围 直接剔除之前的最小值 然后倒数第二个最小值作为队尾
while(tt >= hh && arr[i] <= arr[q[tt]] ) tt--; // 在单调队列中 找一个合适的地方存储 当前arr的值
q[++tt] = i;
if(i-k+1>=0) bw.write(arr[q[hh]] + " ");
}
bw.write("\n");
tt = -1 ;
hh = 0;
// 记录最大值
for(int i = 0 ; i < n ; ++i){
if(tt >= hh && q[hh] < i - k + 1) hh++;
while(tt >= hh && arr[i] >= arr[q[tt]] ) tt--;
q[++tt] = i;
if(i-k+1>=0) bw.write(arr[q[hh]] + " ");;
}
bw.flush();
br.close();
bw.close();
}
}