Problem: AcWing 154. 滑动窗口
@[TOC]
思路
这个问题可以使用滑动窗口和两个单调队列来解决。一个单调队列用来维护窗口内的最大值,另一个单调队列用来维护窗口内的最小值。我们从左到右遍历数组,对于每个元素,我们首先将其加入到两个单调队列中,然后检查窗口的大小是否达到了k。如果达到了,我们就将窗口内的最大值和最小值加入到结果数组中,并移动窗口的左边界。
解题方法
我们首先初始化两个空的单调队列和一个结果数组。然后,我们从左到右遍历输入数组,对于每个元素,我们首先将其加入到两个单调队列中。然后,我们检查窗口的大小是否达到了k。如果达到了,我们就将窗口内的最大值和最小值加入到结果数组中,并移动窗口的左边界。
复杂度
时间复杂度:
,其中n是数组的长度。每个元素只会被加入到单调队列一次,所以时间复杂度是线性的。
空间复杂度:
,在最坏的情况下,两个单调队列中可能会包含所有的元素,所以空间复杂度是线性的。
Code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
public class Main {
static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static StreamTokenizer sr = new StreamTokenizer(in);
static int MAXN = (int) (1e6 + 10);
static int[] arr = new int[MAXN];
static int[] maxdeque = new int[MAXN]; // 最大值单调队列
static int[] mindeque = new int[MAXN]; // 最小值单调队列
static int n, k;
static int maxh, maxt, minh, mint;
public static void main(String[] args) throws IOException {
n = nextInt();
k = nextInt();
maxh = minh = maxt = mint = 0;
for (int i = 0; i < n; i++) {
arr[i] = nextInt();
}
// 首先维持一个k - 1的窗口
for (int i = 0; i < k - 1; i++) {
push(i);
}
int m = n - k + 1; // 存储每个窗口中的最大值和最小值的个数
int[][] ans = new int[MAXN][2]; // 存储结果值
for (int l = 0, r = k - 1; l < m; l++, r++) {
push(r);
// 收集答案
ans[l][0] = arr[maxdeque[maxh]];
ans[l][1] = arr[mindeque[minh]];
// 更新过期值
pop(l);
}
for (int i = 0; i < m; i++) {
out.print(ans[i][1] + " ");
}
out.println();
for (int i = 0; i < m; i++) {
out.print(ans[i][0] + " ");
}
out.flush();
}
private static void pop(int l) {
// TODO Auto-generated method stub
while (maxh < maxt && maxdeque[maxh] <= l) {
maxh++;
}
while (minh < mint && mindeque[minh] <= l) {
minh++;
}
}
private static void push(int i) {
// TODO Auto-generated method stub
// 更新最大值单调队列
while (maxh < maxt && arr[maxdeque[maxt - 1]] <= arr[i]) {
maxt--;
}
maxdeque[maxt++] = i;
// 更新最小值单调队列
while (minh < mint && arr[mindeque[mint - 1]] >= arr[i]) {
mint--;
}
mindeque[mint++] = i;
}
private static int nextInt() throws IOException {
sr.nextToken();
return (int) sr.nval;
}
}