题目
给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2, 3, 4, 2, 6, 2, 5, 1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为{4, 4, 6, 6, 6, 5}
思路:
原文链接:https://blog.csdn.net/littlehaes/article/details/94594006
使用一个双端队列, 将数组中元素的索引依次入队, 入队过程中要始终保持队列首元素对应的值是当前滑窗中所有元素对应的值中最大的
- 遍历数组中的每个元素
- 如果队列为空
- 直接向队列添加当前元素
- 如果队列不为空
- 如果当前元素大于队列末尾对应的元素,则删除队列末尾元素,重复该过程,直到队列为空或者队列末尾对应的元素大于当前元素
- 将当前元素索引加入队列末尾
- 如果当前索引减去队列首元素索引大于等于size, 则说明队首对应元素不在当前滑窗的范围中,删除队首元素
- 如果当前索引大于等于size-1说明滑窗已经框住了size个元素,将队列头部对应的元素添加到最终的ArrayList中
- 如果队列为空
注:如果数组长度为n,窗口大小为w,则一共产生n-w+1个窗口的最大值。
public class Test3 {
public static int[] getMaxWindow(int[] arr, int w) {
int[] res = new int[arr.length - w + 1];
if (arr == null || w < 1 || arr.length < w) {
return null;
}
LinkedList<Integer> qmax = new LinkedList<Integer>();
int index = 0;
for (int i = 0; i < arr.length; i++) {
//队列不为空,且当前元素大于队尾索引对应的元素, 则去掉队尾, 直到队列为空或者当前元素小于队尾索引对应的元素
while (!qmax.isEmpty() && arr[i] >= arr[qmax.peekLast()]) {
System.out.println("qmax.peekLast()==" + qmax.peekLast() + ";arr[i]==" + arr[i]);
qmax.pollLast();
}
qmax.add(i);
System.out.println("qmax:::" + Arrays.toString(qmax.toArray()));
//i-w i=3 w=0;i=4 w= 1 ;i=5 w2
//小于三的范围就是小于窗口范围(过期)
if (qmax.peekLast() - qmax.peekFirst() + 1 > w) {
System.out.println("间距==" + (qmax.peekLast() - qmax.peekFirst() + 1));
qmax.pollFirst();
}
//i大于等于滑窗长度减1时滑窗才是满的
if (i >= w - 1) {
//队列中存的是索引! res中需要加入的是索引对应的元素!
res[index++] = arr[qmax.peekFirst()];
System.out.println("res:::" + Arrays.toString(res));
}
}
return res;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr = { 4, 3, 5, 4, 3, 3, 6, 7 };
int w = 3;
System.out.println(Arrays.toString(getMaxWindow(arr, w)));
}
}
打印结果:
从左到右: [ first ........ last ] 最左边first 是最大值坐标
qmax:::[0]
qmax:::[0, 1]
qmax.peekLast()==1;arr[i]==5
qmax.peekLast()==0;arr[i]==5
qmax:::[2]
res:::[5, 0, 0, 0, 0, 0]
qmax:::[2, 3]
res:::[5, 5, 0, 0, 0, 0]
qmax:::[2, 3, 4]
res:::[5, 5, 5, 0, 0, 0]
qmax.peekLast()==4;arr[i]==3
qmax:::[2, 3, 5]
间距==4
res:::[5, 5, 5, 4, 0, 0]
qmax.peekLast()==5;arr[i]==6
qmax.peekLast()==3;arr[i]==6
qmax:::[6]
res:::[5, 5, 5, 4, 6, 0]
qmax.peekLast()==6;arr[i]==7
qmax:::[7]
res:::[5, 5, 5, 4, 6, 7]
[5, 5, 5, 4, 6, 7]