窗口及窗口内最大值或最小值的更新结构(单调双向队列)详解(java实现)


 * 窗口及窗口内最大值或最小值的更新结构(单调双向队列)
 *
 * 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。
 * 例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5};
 * 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个:
 *          {[2,3,4],2,6,2,5,1},
 *          {2,[3,4,2],6,2,5,1},
 *          {2,3,[4,2,6],2,5,1},
 *          {2,3,4,[2,6,2],5,1},
 *          {2,3,4,2,[6,2,5],1},          
 *          {2,3,4,2,6,[2,5,1]}。

思路:用双端队列,实现窗口最大值的更新,生成双端队列,qmax={},双端队列中存放着数组中的下标值,
假设当前数为arr[i],放入规则如下:
1、如果qmax为空,直接把下标i放入qmax中
2、如果qmax不为空,去当前qmax存放的下标j,如果arr[j]>arr[i],直接把下标i放进qmax的队尾,放入过程直接结束。
3、如果arr[j]<=arr[i],则一直从amax的队尾弹出下标,知道某个下标在array中对应的值大于arr[i],把i放入qmax的队尾。
假设当前数组arr[i],弹出规则为:
如果qmax对头的下标等于i-w,说明当前队头下标已经过期,则弹出qmax当前队头下标,
根据如上放入弹出规则,可知qmax成为一个维护窗口为w的子数组最大值的更新结构。

时间复杂度O(N)。


import java.util.HashMap;
import java.util.LinkedList;
public class Code_01_SlidingWindowMaxArray {
    public static int[] getMaxWindow(int[] arr, int w) {
        if(arr == null || w < 1 || arr.length < w){
            return null;
        }
        
        LinkedList<Integer> qmax = new LinkedList<Integer>();//双向链表,双端队列
        int[] res = new int[arr.length - w + 1];
        int index = 0;
        for (int i = 0; i < arr.length; i++) {
            while (!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[i]) {
                qmax.pollLast();
            }
            qmax.addLast(i);
            if(qmax.peekFirst() == i - w){
                qmax.pollFirst();
            }
            if (i >= w - 1) {
                res[index++] = arr[qmax.peekFirst()];
            }
        }
        return res;
    }
        
    public static void main(String[] args) {
        int[] arr={2,3,4,2,6,2,5,1};
        int[] maxWindow = getMaxWindow(arr, 3);
        for (int i = 0; i < maxWindow.length; i++) {
            System.out.print(maxWindow[i]+"-");
        }
    }
}



猜你喜欢

转载自blog.csdn.net/u012469528/article/details/80774776
今日推荐