滑动窗口最大值

滑动窗口最大值

1、题目描述

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
在这里插入图片描述

2、解答思路

本题需要遍历每个滑动窗口,然后求出滑动窗口的最大值,重点在于如何将求出滑动窗口最大值的时间复杂度降到O(1)。因此可以使用单调的双端队列。假设循环遍历将nums[i]添加到队列中,每次将i++,那么滑动窗口往后移一位。

  • 在讨论下一个滑动窗口之前,判断当前窗口的最大值是否是对应数组的第一个元素,若是,即当前窗口的元素个数为k,则移除第一个元素,以便后续元素加入。
  • 若nums[i]大于队列中的末尾元素,则移除队列中所有小于nums[i]的元素,确保队列的单调属性,相当于比较得出较大的元素。
  • 若nums[i]小于队列中的末尾元素,则直接添加到队列末尾,不移除的原因是其可能成为后面滑动窗口的最大值。
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        // 定义结果数组
        int[] ans = new int[nums.length-k+1];
        // 结果数组的下标
        int index = 0;
        // 定义单调双端队列
        Deque<Integer> deque = new LinkedList<>();

        // 未形成窗口之前
        for(int i=0;i<k;i++){
            // 移除队列中所有小于num[i])的元素,确保队列单调递减
            while(!deque.isEmpty() && deque.peekLast()<nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
        }
        // 获取第一个窗口的最大值
        ans[index++] = deque.peekFirst();

        // 形成窗口之后
        for(int i=k;i<nums.length;i++){
            // 如果之前窗口的最大值为对于数组的第一个元素,即滑动窗口满了,则移除第一个元素
            if(deque.peekFirst() == nums[i-k])
                deque.removeFirst();
            // 移除队列中所有小于num[i])的元素,确保队列单调递减
            while(!deque.isEmpty() && deque.peekLast()<nums[i])
                deque.removeLast();
            deque.addLast(nums[i]);
            ans[index++] = deque.peekFirst();
        }
        return ans;
    }
}
  • 时间复杂度 O(n) : 其中 n 为数组 nums 长度。线性遍历 nums 占用 O(n) ;每个元素最多仅入队和出队一次,因此单调队列 deque 占用 O(2n) ,因此总的来说是O(n)。
  • 空间复杂度 O(k) : 双端队列 deque 中最多同时存储 k 个元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值