【leetcode】239.滑动窗口最大值

81 阅读2分钟

leetcode-239.png

题目简述:给定一个数组,还有一个k值,代表窗口大小,记录每次窗口中最大的值,最后将最大值放到数组中进行返回。
这一题的描述,大概就是我的思路,可惜最后不能ac(超时),下面放出我的耿直代码。

未能ac代码1

var maxSlidingWindow = function (nums, k) {
    if (k === 1) return nums
    let res = []
    for (let i = 0; i < nums.length; ++i) {
        let maxNum = -Infinity
        let tail = i + k < nums.length ? i + k : nums.length
        if (i + k === nums.length + 1) break
        for (let j = i; j < tail; ++j) {
            maxNum = Math.max(maxNum, nums[j])
        }
        res.push(maxNum)
    }
    return res
};

Time Limit Exceeded1.png

既然耿直的思路不行,那肯定有巧妙的思路,我想到的就是,记录窗口内最大值maxNum,然后下次进来的数字就跟maxNum进行比较,但是这里还存在一个问题,滑动出去的数字可能是最大数字,那就又要处理这个逻辑了

未能ac代码2

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

这种解法又又又超时了 Time Limit Exceeded2.png 所以肯定还有更屌的思路

双端队列

使用queue来维护,里面存放的元素是递减数列的索引,队头始终存放当前窗口内最大元素的索引

  • 移除不在当前滑动窗口范围内的索引(即队列头部的索引小于 i - k + 1)。

  • 移除所有比当前元素小的元素索引(从队列尾部开始),以确保队列中的元素按降序排列。

  • 将当前元素的索引添加到队列。

  • 当窗口大小达到 k 时,记录当前窗口的最大值(即队列头部的元素)。

var maxSlidingWindow = function (nums, k) {
    if (k === 1) return nums
    let res = []
    let queue = []
    for (let i = 0; i < nums.length; ++i) {
        // 移除不在滑动窗口内的元素
        if (queue.length && queue[0] < i - k + 1) {
            queue.shift()
        }
        // 当前元素大于queue里面索引所指向的元素,将小的元素索引出队
        while (queue.length && nums[queue[queue.length - 1]] < nums[i]) {
            queue.pop()
        }
        // 将当前索引放入队列
        queue.push(i)
        // 窗口满足要求时,将queue队头指向的元素放入res中
        if (i >= k - 1) {
            res.push(nums[queue[0]])
        }
    }
    return res
};