问题描述
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
进阶:
你能在线性时间复杂度内解决此题吗?
示例:
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7]
解释:
1 | 滑动窗口的位置 最大值 |
来源:LeetCode
解法一
首先看暴力解法,设nums的长度为n,则主循环遍历n-k+1次,子循环k次,即可完成对每个窗口的求解,时间复杂度是O(nk)。根据窗口的定义,我们只需要维护窗口的元素,并提供一个接口,查询当前窗口的最大值。维持大小为k的大顶堆可以查询最大值,但在维护窗口上,删除上一个窗口的第一个元素,需要花费的时间不得而知,因为堆只是维持父子节点的弱有序,查询的复杂度是不确切的。
因为在窗口滑动时,我们需要删除上一个窗口的第一个元素,且最好能在O(1)的时间里删除,则可以尝试队列,同时,为了提供查询窗口最大值的接口,我们把front设置成最大值的索引,front到back的元素是小于front的元素。这里使用索引而不是最大值,是因为如果是最大值,我们无法确认是否front是否还在当前窗口内。front的维护方法,窗口移动得到的新元素与队列中的back比较,如果比back大,则弹出back(这里用到pop_back,所以用的队列就是双端队列),因为back不可能是最大值,堵在队列中会影响front(试想front因为窗口滑动而退出,此时新的front是较小的元素,那么front就不是最大值了)。
1 | class Solution { |