数据结构--窗口内最大值最小值的更新结构(单调双向队列)
窗口内最大值最小值的更新结构(单调双向队列)
窗口滑动的规则:
L,R开始均指向数组的最左边,L < R,
窗口内增加元素:R向右走,
窗口内减少元素:L向右走
R和L均不能向后退,只能向前走
数组array
采用双端链表LingkedList(双端队列)(index(在数组中的位置,可以用来表示过期没过期),value(在数组中的值)),链表内保证 尾进头出,且保证从头到尾是从大到小排序
当窗口内加数num时,从尾部进入,若尾部当前数大于num,则直接放入,若当前元素小于或等于num,则将其弹出,一直到满足其中的数大于num或者弹空了,保证降序排列。
当窗口减数num时,检查头部的数的index,如果是已经过期(即数组中该数不在窗口内)则从头部弹出
注:可以在双端队列中只存下标,因为可以从数组array中通过下标拿到值
生成窗口最大值数组
有一个整型数组arr和一个大小为w的窗口从数组的最左边滑到最右边, 窗口每次向右边滑一个位置。
例如, 数组为[4,3,5,4,3,3,6,7], 窗口大小为3时:
[4 3 5] 4 3 3 6 7 窗口中最大值为5
4 [3 5 4] 3 3 6 7 窗口中最大值为5
4 3 [5 4 3] 3 6 7 窗口中最大值为5
4 3 5 [4 3 3] 6 7 窗口中最大值为4
4 3 5 4 [3 3 6] 7 窗口中最大值为6
4 3 5 4 3 [3 6 7] 窗口中最大值为7
如果数组长度为n, 窗口大小为w, 则一共产生n-w+1个窗口的最大值。
请实现一个函数。
输入: 整型数组arr, 窗口大小为w。
输出: 一个长度为n-w+1的数组res, res[i]表示每一种窗口状态下的最大值。
以本题为例, 结果应该返回{5,5,5,4,6,7}。
public class SlidingWindowMaxArray { public static int[] getMaxWindow(int[] arrays, int k){ if(arrays == null || arrays.length == 0) return null; LinkedList<Integer> list = new LinkedList<>(); int[] res = new int[arrays.length - k + 1]; int x = 0; for(int i = 0; i < arrays.length; i++){ while(!list.isEmpty() && arrays[list.peekLast()] <= arrays[i]){ list.pollLast(); } list.addLast(i); //判断是否过期 while(list.peekFirst() == i - k){ list.pollFirst(); } //窗口大小超过k if(i >= k - 1){ res[x++] = arrays[list.peekFirst()]; } } return res; } public static void printArray(int[] arr) { for (int i = 0; i != arr.length; i++) { System.out.print(arr[i] + " "); } System.out.println(); } public static void main(String[] args) { int[] arr = { 4, 3, 5, 4, 3, 3, 6, 7 }; int w = 3; printArray(getMaxWindow(arr, w)); } }