【Offer】[59-1] 【滑动窗口的最大值】

题目描述

  给定一个数组和滑动窗口的大小,请找出所有滑动窗口里的最大值。例如,如果输入数组{2,3,4,2,6,2, 5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,它们的最大值分别为{4,4,6,6,6,5},如下表所示:

牛客网刷题地址

思路分析

  建立一个两端开口的队列,放置所有可能是最大值的数字(存放的其实是对应的下标),且最大值位于队列开头。从头开始扫描数组,

  1. 如果遇到的数字比队列中所有的数字都大,那么它就是最大值,其它数字不可能是最大值了,将队列中的所有数字清空,放入该数字,该数字位于队列头部;
  2. 如果遇到的数字比队列中的所有数字都小,那么它还有可能成为之后滑动窗口的最大值,放入队列的末尾;
  3. 如果遇到的数字比队列中最大值小,最小值大,那么将比它小数字不可能成为最大值了,删除较小的数字,放入该数字。
  4. 由于滑动窗口有大小,因此,队列头部的数字如果其下标离滑动窗口末尾的距离大于窗口大小,那么也删除队列头部的数字。
  5. 队列中存放的是数字的下标

测试用例

  1. 功能测试:输入数组的数字大小无序;输入数组的数字单调递增;输入数组的数字单调递减。
  2. 边界值测试:滑动窗口的大小为0、1、等于输入数组的长度、大于输入数组的长度。
  3. 特殊输入测试:输入数组为空。

Java代码

public class Offer059_01 {
    public static void main(String[] args) {
        test1();
        test2();
        test3();

    }

    public static ArrayList<Integer> maxInWindows(int[] num, int size) {
        return Solution1(num, size);
    }

    private static ArrayList<Integer> Solution1(int[] num, int size) {
        ArrayList<Integer> max = new ArrayList<Integer>();
        if (num == null || num.length <= 0 || size <= 0 || size > num.length)
            return max;
        ArrayDeque<Integer> indexDeque = new ArrayDeque<Integer>();

        for (int i = 0; i < size - 1; i++) {
            while (!indexDeque.isEmpty() && num[i] > num[indexDeque.getLast()])
                indexDeque.removeLast();
            indexDeque.addLast(i);
        }

        for (int i = size - 1; i < num.length; i++) {
            while (!indexDeque.isEmpty() && num[i] > num[indexDeque.getLast()])
                indexDeque.removeLast();
            if (!indexDeque.isEmpty() && (i - indexDeque.getFirst()) >= size)
                indexDeque.removeFirst();
            indexDeque.addLast(i);
            max.add(num[indexDeque.getFirst()]);
        }

        return max;
    }

    private static void test1() {

    }
    private static void test2() {

    }
    private static void test3() {

    }

}

代码链接

剑指Offer代码-Java

原文地址:https://www.cnblogs.com/haoworld/p/offer591-hua-dong-chuang-kou-de-zui-da-zhi.html