什么是滑动窗口
滑动窗口最大值问题是一个经典的问题,它的意思是给定一个长度为n的数组nums,以及一个窗口的长度k,要求找到每次滑动窗口时,窗口内的最大值。
以下是一种基于双端队列的滑动窗口最大值算法套路框架:
1.初始化一个大小为k的双端队列queue,并将数组的前k个元素入队。
2.从数组的第k+1个元素开始遍历,每次遍历时,先将队列中的最右边的元素出队,然后将当前元素与队列中最左边的元素比较,如果当前元素比队列中最左边的元素大,则将当前元素入队。
3.遍历完整个数组后,队列中剩下的元素就是所有滑动窗口的最大值。
实战:返回数组每次滑出状况的最大值
题目描述
窗口内最大值或最小值更新结构的实现 假设一个固定大小为W的窗口,依次划过arr, 返回每一次滑出状况的最大值 例如,arr = [4,3,5,4,3,3,6,7], W = 3 返回:[5,5,5,4,6,7]
解题思路
需要返回的数组长度就是,原始数组长度 - W + 1.
我们按滑动窗口最大值的更新结构,每次我们将窗口内的最大值,
从双端队列的右边加进去.滑出时加到要返回的数组.代码演示下.
代码演示
/**
* 滑动窗口最大值
* @param arr
* @param w
* @return
*/
public static int[] getMaxWindow(int[] arr, int w) {
if (arr == null || arr.length == 0 || w > arr.length){
return null;
}
int index = 0;
//双端队列 记录窗口最大值
int N = arr.length;
//记录窗口内的最大值 保存下标
LinkedList<Integer> qMax = new LinkedList<>();
int[] ans = new int[N - w + 1];
//从0 位置开始一步步去滑动窗口
for (int R = 0; R < N ;R++){
//先检查新进来一个数时,前面比其小的数字弹出
while (!qMax.isEmpty() && arr[qMax.peekLast()] <= arr[R]){
qMax.pollLast();
}
//新来的数字加进来,这里加的是下标,从队尾加进来
qMax.addLast(R);
//检查窗口是否有过期下标,窗口滑过去了,就将其弹出去
if (qMax.peekFirst() == (R - w)){
qMax.pollFirst();
}
//窗口是否形成.
if (R >= w - 1){
ans[index++] = arr[qMax.peekFirst()];
}
}
return ans;
}