菜鸡的算法修炼——队列(滑动窗口的最大值)

题目描述(引自剑指offer)

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

数组中的滑动窗口
滑动窗口中的最大值
[2,3,4],2,6,2,5,14
2,[3,4,2],6,2,5,1
4
2,3,[4,2,6],2,5,1
6
2,3,4,[2,6,2],5,1
6
2,3,4,2,[6,2,5],1
6
2,3,4,2,6,[2,5,1]
5

菜鸡与大佬的对话

菜鸡修炼坊

题目分析

经过在菜鸡修炼坊的修炼,菜鸡对线性表有了一个整体的把握。于是,菜鸡鼓起勇气向题目发起挑战。

掌握了线性表的菜鸡已经自动忽略了题目的暴力解法。一番分析之后,菜鸡发现,一个滑动窗口可以看作一个队列。窗口滑动的过程对应着队首元素出队和新元素入队的过程。而问题的关键就在于如何从队列中找到最大值。菜鸡很快想到可以利用辅助栈来记录队列每时每刻的最大值。忽然间,菜鸡脑中灵光一闪,是否可以定义一种数据结构,可以同时满足队列和栈的特性。查阅资料之后,菜鸡震惊地发现确实有这样一种数据结构,名为双端队列。


菜鸡开始明白大佬所说的“修炼要融会贯通”是什么意思,也渐渐体会到思想的重要性。菜鸡内心波澜四起,那种冲击不是成功解答几道题目可比的。菜鸡意识到,这可能才是修炼的意义所在。思考过后,菜鸡决定用Java代码把自己的心路历程描绘出来。

代码实现

import java.util.ArrayList;
import java.util.LinkedList;


public class Solution {


    public ArrayList<Integer> maxInWindows(int[] num, int size) { 


        ArrayList<Integer> result = new ArrayList<>();
        
        if (num == null || num.length == 0 || size < 1 || size > num.length) {
            return result;
        }


        // 申请一个LinkedList用作双端队列
        // 双端队列可以看作同时拥有栈和队列特性的数据结构
        LinkedList<Integer> queue = new LinkedList<>();
        
        for (int i = 0; i < num.length; i++) {
            // 出栈
            while (!queue.isEmpty() && num[queue.peekLast()] < num[i]) {
                queue.pollLast();
            }
            // 入队(入栈)
            queue.offerLast(i);
            // 出队
            if (queue.peekFirst() == i - size) {
                queue.pollFirst();
            }
            // 记录结果
            if (i >= size - 1) {
                result.add(num[queue.peekFirst()]);
            }
        }
        
        return result;
    }
    
}

写罢之后,菜鸡发现只要遍历一次数组即可得到结果,因此代码的时间复杂度为o(n)。此次修炼之后,菜鸡对之前几次修炼的内容也进行了一次总结回顾,夯实基本功,期待新的突破。

相关链接

算法——查找

菜鸡的算法修炼——链表(反转链表)

菜鸡的算法修炼——栈(栈的压入,弹出序列)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值