AcWing 154. 滑动窗口

60 阅读2分钟

Problem: AcWing 154. 滑动窗口

@[TOC]

思路

这个问题可以使用滑动窗口和两个单调队列来解决。一个单调队列用来维护窗口内的最大值,另一个单调队列用来维护窗口内的最小值。我们从左到右遍历数组,对于每个元素,我们首先将其加入到两个单调队列中,然后检查窗口的大小是否达到了k。如果达到了,我们就将窗口内的最大值和最小值加入到结果数组中,并移动窗口的左边界。

解题方法

我们首先初始化两个空的单调队列和一个结果数组。然后,我们从左到右遍历输入数组,对于每个元素,我们首先将其加入到两个单调队列中。然后,我们检查窗口的大小是否达到了k。如果达到了,我们就将窗口内的最大值和最小值加入到结果数组中,并移动窗口的左边界。

复杂度

时间复杂度:

O(n)O(n),其中n是数组的长度。每个元素只会被加入到单调队列一次,所以时间复杂度是线性的。

空间复杂度:

O(n)O(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;
	}

}