随着做题多了,最大的感受是,什么就是不要慌,即使一下子接口完了用不对,或者逻辑不对,导致的结果不对,都可以用:

极简案例数据 + 断点调试+解题思路!, 按照你的解题思路把结果给一步步找到,只要按照步骤来,观察每个步骤的对错就可以了!

解题思路:

第一种:窗口列表,遍历窗口最大值

1、我自己的解法,是用一个queue记录最大值,之后再通过遍历窗口queue获得最大值,welll done!~~我自己做出来的!

第二种:双向队列获取窗口最大值

官方的做法,则是高效许多,一个双向队列,搞定窗口移动过程中的最大值加入和淘汰,只是这个队列保存值比较特殊,是数组下标的index,为什么这样做?因为要用于淘汰掉,已经远离了当前窗口的旧数据。

具体做法:

1、定义一个双向队列,先初始化,填充 [0,size-1],值最大值的下标index!

2、之后,从size开始,遍历整个数组,逐渐找出下标最大的值,同样只要做好两件事就好了:

1)记录当前窗口,值最大的下标到队列

2)淘汰掉已经出了当前窗口的下标值

import java.util.*;


public class Solution {

   /**
     * 这是我自己使用的方法,其实引入最大堆是浪费,
	 * queue遍历的过程中就可以获得最大值了,所以无需最大堆浪费空间
     * @param num int整型一维数组
     * @param size int整型
     * @return int整型ArrayList
     */
    public ArrayList<Integer> maxInWindows2 (int[] num, int size) {
        ArrayList<Integer> res = new  ArrayList<Integer>();
        if (num == null || num.length == 0 || size == 0) {
            return res;
        }
        PriorityQueue<Integer> max = new PriorityQueue<Integer>((o1,
                o2)->o2.compareTo(o1));
        LinkedList<Integer> queue = new LinkedList<Integer>();

        for (int i = 0; i < size; i++) {
            max.offer(num[i]);
            queue.offer(num[i]);
        }
        res.add(max.peek());

        int j = size;
        int n = num.length;
        while (j < n) {
            queue.offer(num[j]);
            queue.poll();
            int maxInWin = addMaxInWindows(queue, max);
            res.add(maxInWin);
            j++;
        }

        return res;
    }

    private int addMaxInWindows(LinkedList<Integer> queue,
                                PriorityQueue<Integer> max) {
        max.clear();
        for (int i = 0; i < queue.size(); i++) {
            max.offer(queue.get(i));
        }
        return max.peek();
    }

    /**
     * 官方的方法,只是引入了双向队列arrayqueue就搞定了滑动窗口最大值的保存了
     * @param num int整型一维数组
     * @param size int整型
     * @return int整型ArrayList
     */
    public ArrayList<Integer> maxInWindows (int[] num, int size) {
        ArrayList<Integer> res = new  ArrayList<Integer>();
        if (num == null || num.length == 0 || size == 0 || num.length < size) {
            return res;
        }

        ArrayDeque<Integer> q = new ArrayDeque<Integer>();
        for (int i = 0; i < size; i++) {
            // 淘汰掉小的数据
            while (!q.isEmpty() && num[q.peekLast()] < num[i])
                q.pollLast();
            q.offer(i);
        }

        int n = num.length;
        for (int i = size; i < n; i++) {
            res.add(num[q.peekFirst()]);
            // 淘汰掉已经过了当前滑动窗口的数据
            while (!q.isEmpty() && q.peekFirst() < (i - size + 1))
                q.pollFirst();
            // 跟上面一样,淘汰掉队列里小的数据
            while (!q.isEmpty() && num[q.peekLast()] < num[i])
                q.pollLast();
            q.offer(i);
        }

        res.add(num[q.peekFirst()]);
        return res;
    }
}