61 滑动窗口的最大值

题目
  给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值