zoukankan      html  css  js  c++  java
  • 剑指64.滑动窗口的最大值

    题目描述

    给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。
    窗口大于数组长度的时候,返回空
     

    思路

    一个滑动窗口可以看成一个队列,当窗口滑动时,处于窗口的第一个数字被删除,同时在窗口的末尾添加一个新的数字,这符合队列“先进先出”。

    思路1:暴力法。时间复杂度为O(nk)

    思路2:增减维护一个优先队列。时间复杂度O(n logk)

    思路3:通过单调Deque双端队列。Deque里头最大,尾最小。注意Deque里存的是index,不是值。                          (时间复杂度O(n),每个下标最多进一次,出一次。)

    一共有n-(size-1)个滑动窗口

    注意要分清队列的头和尾,“头在左,尾在右”。因为,窗口向右移动,队列是尾入头出。

    步骤:头尾尾头

    • 1)头部出队
    • 2)尾部清理(因为要删除尾部,所以要用双端队列)
    • 3)尾部入队
    • 4)返回头部(从左往右看)

    ☆☆☆☆解法

    import java.util.ArrayList;
    import java.util.Deque;
    import java.util.LinkedList;
    public class Solution {
        public ArrayList<Integer> maxInWindows(int [] num, int size) {
            ArrayList<Integer> list = new ArrayList<>();
            if (num == null || size < 1 || num.length < size)
                return list;
            // 双端队列,deque里存的是数组的index,不是数组的值
            Deque<Integer> deque = new LinkedList<>();
            for (int i = 0; i < num.length; i++) {
                //Step1: 头: 移除头部, 保证窗口的长度范围
                if (!deque.isEmpty() && (i - deque.getFirst()) >= size){ //这个条件也可以换成 deque.getFirst() < (i - (size - 1))
                    deque.removeFirst();
                }
                //Step2: 尾: 移除尾部小于当前值的元素, 去除不可能的元素
                while (!deque.isEmpty() && num[i] >= num[deque.getLast()]){
                    deque.removeLast();
                }
                //Step3: 尾部加入, 滑动窗口向右扩充
                deque.addLast(i);
                //Step4: 头, 从头部返回极大值
                if (i >= size - 1){
                    list.add(num[deque.getFirst()]);
                    //list.add(num[deque.peekFirst()]); //所有的dq.getFirst()也可以换为dq.peekFirst()
                }
            }
            return list;
        }
    }

    参考:

    易懂视频 java版本 双端队列的讲解

  • 相关阅读:
    03-串联
    大数据项目之电商数仓(3电商数据仓库系统)V6.1.3
    JQuery实现tab页
    Java面试题之计算字符/字符串出现的次数
    ios 苹果内购订单验证 --- nodejs实现
    ios 苹果内购订单验证 --- php实现
    Android内购订单验证 --- nodejs实现
    Android内购订单验证 --- php实现
    Google Compute Engine VM自动调节
    php性能优化 --- laravel 性能优化
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/13649894.html
Copyright © 2011-2022 走看看