题解 | #滑动窗口的最大值#

滑动窗口的最大值

https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param num int整型一维数组
     * @param size int整型
     * @return int整型ArrayList
     */
    public ArrayList<Integer> maxInWindows (int[] num, int size) {
        // write code here
        // 核心思想:设置一个【单调双端队列】,确保队头是当前窗口内的最大值

        // 0.判断特殊情况
        ArrayList<Integer> result = new ArrayList<>();
        if (size <= 0 || size > num.length) {
            return result;
        }

        // 1.创建双端队列
        Deque<Integer> dq = new LinkedList<>();

        // 2.录入初始窗口
        int h = 0;
        int t = size - 1;
        for (int i = h; i <= t; i++) {
            // 录入的是下标
            inDequeue(num, i, dq);
        }

        // 3.得到初始窗口的结果
        // 注意!从队列中取出来的是下标值,要转换成元素值存入结果中
        result.add(num[dq.peekFirst()]);

        // 4.模拟窗口移动-h右移且t右移,不断得到结果
        for (int i = 1; i <= (num.length - size); i++) {
            // 4.1 t后移,新元素入队
            inDequeue(num, ++t, dq);
            // 4.2 h后移,旧元素出队
            outDequeue(num, h++, dq);
            // 4.3 新窗口形成,从队头获得当前窗口最大元素
            // 注意!从队列中取出来的是下标值,要转换成元素值存入结果中
            result.add(num[dq.peekFirst()]);
        }

        return result;
    }

    // 新元素入单调双端队列的操作
    public void inDequeue(int[] num, int i, Deque<Integer> dq) {
        // 录入的是下标
        if (dq.isEmpty()) {
            // 若队列为空,则直接录入
            dq.addLast(i);
        }
        else if (num[i] < num[dq.peekLast()]) {
            // 若待录入元素小于队尾元素,则入队
            dq.addLast(i);
        } else {
            // 若待录入元素大于等于队尾元素,则不断地让堆尾元素出队,直到满足小于队尾元素入队
            // 等于也要出队的目的是让新的元素替代队列中旧的元素
            while (!dq.isEmpty() && num[i] >= num[dq.peekLast()]) {
                dq.pollLast();
            }
            // 此时队列空了,或者队尾下标元素大于当前待入队元素
            dq.addLast(i);
        }
    }

    // 旧元素出单调双端队列的操作
    public void outDequeue(int[] num, int i, Deque<Integer> dq) {
        // 录入的是下标
        if (i == dq.peekFirst()) {
            // 当待出队元素正好是队头元素(当前窗口最大)时才出队
            dq.pollFirst();
        }
        // 当待出队元素不是队头元素(当前窗口最大)时不用出队
    }
}

全部评论

相关推荐

我就是0offer糕手:北大不乱杀
点赞 评论 收藏
分享
asdasdasdasdas:19岁,不容易啊可能升个本会好点,现在学历歧视太严重了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务