「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战」。
一、滑动窗口是什么?
滑动窗口(SlidingWindow)是一种想象出来的数据结构,滑动窗口有左边界L和右边界R。在数组或者字符串或者一个序列上,记为S,窗口就是S[L..R]这一部分,L往右滑意味着一个样本出了窗口,R往右滑意味着一个样本进了窗口,L和R都只能往右滑。
二、滑动窗口能做什么?
窗口不管L还是R滑动之后,都会让窗口呈现新状况,如何能够更快的得到窗口当前状况下的最大值和最小值?最好平均下来复杂度能够做到O(1)。
利用单调双端队列!不了解什么是双端队列,可以参考这篇文章。
三、滑动窗口实现思路
四、滑动窗口题目
滑动窗口实现窗口内最大值
假设一个固定大小为W的窗口,依次划过arr,
返回每一次滑出状况的最大值
例如,arr = [4,3,5,4,3,3,6,7], W = 3
返回:[5,5,5,4,6,7]
暴力实现
public static int[] right(int[] arr, int w) {
if (arr == null || w < 1 || arr.length < w) {
return null;
}
int N = arr.length;
int L = 0;
int R = w - 1;
int[] ans = new int[N - w + 1];
int index = 0;
while (R < N) {
int max = arr[L];
for (int i = L + 1; i <= R; i++) {
max = Math.max(max, arr[i]);
}
ans[index++] = max;
R++;
L++;
}
return ans;
}
利用滑动窗口实现
// 利用滑动窗口,双端队列
public static int[] getMaxWindow(int[] arr, int w) {
if (arr == null || w < 1 || arr.length < w) {
return null;
}
LinkedList<Integer> queueMax = new LinkedList<>();
int[] res = new int[arr.length - w + 1];
int index = 0;
for (int R = 0; R < arr.length; R++) {
while (!queueMax.isEmpty() && arr[queueMax.peekLast()] <= arr[R]) {
queueMax.pollLast();
}
queueMax.addLast(R);
// 窗口过期下标
if (queueMax.peekFirst() == R - w) {
queueMax.pollFirst();
}
// 窗口预热,达到窗口大小时收集答案
// 是否现在形成了正常窗口,窗口在未形成时,窗口属于培养期,不需要收集答案
if (R >= w - 1) {
res[index++] = arr[queueMax.peekFirst()];
}
}
return res;
}
test
public static void main(String[] args) {
int[] arr = {4, 3, 5, 4, 3, 3, 6, 7};
int w = 3;
System.out.println(Arrays.toString(right(arr, w)));
System.out.println(Arrays.toString(getMaxWindow(arr, w)));
}