学习记录:js算法(二十三):滑动窗口最大值

滑动窗口最大值

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

示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7
 
示例 2:
输入:nums = [1], k = 1
输出:[1]

思路一

var maxSlidingWindow = function (nums, k) {
    let result = [];
    for (let i = 0; i <= nums.length - k; i++) {
        let max = nums[i];
        for (let j = 1; j < k; j++) {
            if (nums[i + j] > max) {
                max = nums[i + j];
            }
        }
        result.push(max);
    }
    return result;
};

讲解
两个循环解决问题。
外层循环:遍历 从 0 到 nums.length - k,每次确定一个 窗口的起始位置
内层循环:在当前窗口内 (从 i 到 i + k - 1) 查找最大值。
然后将值存储到 result 中就行。

思路二

var maxSlidingWindow = function (nums, k) {
    let result = [];
    let deque = []; // 用于存储索引
    for (let i = 0; i < nums.length; i++) {
        // 移除不在窗口内的元素
        if (deque.length && deque[0] < i - k + 1) {
            deque.shift();
        }
        // 移除小于当前元素的索引
        while (deque.length && nums[deque[deque.length - 1]] < nums[i]) {
            deque.pop();
        }
        // 添加当前元素的索引
        deque.push(i);
        // 当窗口达到大小 k 时,记录当前窗口的最大值
        if (i >= k - 1) {
            result.push(nums[deque[0]]);
        }
    }
    return result;
};

讲解
具体的解题思路:

  1. 滑动窗口:我们可以使用一个大小为 k 的窗口,从数组的左侧开始,逐步向右滑动。
  2. 双端队列:使用一个双端队列(deque)来存储当前窗口内的元素的索引。这个队列的特点是:
    队列的头部始终存储当前窗口的最大值的索引。
    队列中的索引是单调递减的,即队列头部的元素对应的值是当前窗口内最大的。

具体分析

  1. 初始化:创建一个空的结果数组 result 和一个空的双端队列 deque
  2. 遍历数组:对于每个元素 nums[i]
    移除过期元素:检查队列的头部,如果它的索引小于 i - k + 1(表示该索引不在当前窗口内),则将其移除。
    保持单调性:在添加新元素之前,移除队列中所有小于当前元素的索引。这是因为这些元素在当前窗口中不可能是最大值。
    添加当前元素的索引:将当前元素的索引 i 添加到队列中。
    记录最大值:当 i大于等于 k - 1 时,将队列头部的元素(即当前窗口的最大值)添加到结果数组中。

关键点
双端队列的使用:它的特性使得我们能够快速地添加和移除元素,同时保持当前窗口的最大值在队列的头部。
窗口的更新:通过维护一个有效的索引集合,我们能够在短时间内获取当前窗口的最大值,避免了重复计算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值