经典算法思想之滑动窗口

经典算法思想之滑动窗口

滑动窗口

https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/

剑指 Offer 59 - I. 滑动窗口的最大值
给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:

滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

分析:
数组的长度为n 窗口的大小为k 可形成的窗口个数 n-k+1

通过队列来记录最大值

窗口未形成的阶段
遍历数组,同时更新队列

窗口已形成的阶段
每次窗口移动,都是在头部移除元素,尾部增加元素
在窗口变化过程中 记录其最大值的变化 (让最大值一直出现在第一位)

让队列中已存在的元素 和新添加的元素比较 如果已存在的更小 那么覆盖
如果已存在的更大 新添加的元素是候选 缀到队列之后

滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

窗口 max队列
[1 3 -1] [1] -> [3] -> [3,-1]
[3 -1 -3] [3,-1,-3]
[-1 -3 5] [-1,-3] -> [5]
[-3 5 3] [5,3]
[5 3 6] [6]
[3 6 7] [7]

public static int[] maxSlidingWindow(int[] nums, int k) {

        // 记录每个窗口的最大值   n-k+1为形成的窗口个数
        int[] result = new int[nums.length - k + 1];

        // 使用队列记录最大值的候选值
        Deque<Integer> deque = new ArrayDeque<>();

        // 窗口未形成的阶段
        for (int i = 0; i < k; i++) {
            print(deque);
            // 每次都取 队尾元素和新元素 比较  如果队尾更小  删除
            while (!deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.pollLast();
            }
            deque.offerLast(nums[i]);
        }

        // 此时第一个窗口形成  deque的队头元素就是第一个窗口的最大值
        result[0] = deque.peekFirst();
        print(deque);

        // 窗口已形成的阶段
        for (int i = k; i < nums.length; i++) {
            System.out.println("-----第" + (i-k+1) + "次滑动");
            // 删了元素 nums[i-k]  添了元素 nums[i]
            if(nums[i-k] == deque.peekFirst()){
                // 如果删的是最大值  同时从deque移除
                deque.pollFirst();
            }

            // 新增
            while (!deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.pollLast();
            }
            deque.offerLast(nums[i]);

            result[i-k+1] = deque.peekFirst();
            print(deque);
        }

        return result;
    }


    public static void print(Deque<Integer> deque){
        for (Integer integer : deque) {
            System.out.print(integer + " ");
        }
        System.out.println();
    }
上一篇:C++学习笔记 (五)标准模板库STL之容器


下一篇:[转载]C++ STL 双端队列deque详解