一、题目描述
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
进阶:
你能在线性时间复杂度内解决此题吗?
示例:
提示:
二、解题思路 & 代码
2.1 暴力法
最简单直接的方法是遍历每个滑动窗口,找到每个窗口的最大值。一共有 N - k + 1
个滑动窗口,每个有 k
个元素,于是算法的时间复杂度为 ,表现较差。
复杂度分析
- 时间复杂度:。其中 N 为数组中元素个数。
- 空间复杂度:,用于输出数组。
2.2 双向队列
遍历数组,将 数 存放在双向队列中,并用 L
,R
来标记窗口的左边界和右边界。队列中保存的并不是真的 数,而是该数值对应的数组下标位置,并且数组中的数要从大到小排序。如果当前遍历的数比队尾的值大,则需要弹出队尾值,直到队列重新满足从大到小的要求。刚开始遍历时,L
和 R
都为 0,有一个形成窗口的过程,此过程没有最大值,L
不动,R
向右移。当窗口大小形成时,L
和 R
一起向右移,每次移动时,判断队首的值的数组下标是否在 [L,R]
中,如果不在则需要弹出队首的值,当前窗口的最大值即为队首的数。
示例:
- 通过示例发现
R=i
,L=k-R
。由于队列中的值是从大到小排序的,所以每次窗口变动时,只需要判断队首的值是否还在窗口中就行了。 - 解释一下为什么队列中要存放数组下标的值而不是直接存储数值,因为要判断队首的值是否在窗口范围内,由数组下标取值很方便,而由值取数组下标不是很方便。
复杂度分析
- 时间复杂度:,每个元素被处理两次- 其索引被添加到双向队列中和被双向队列删除。
- 空间复杂度:,输出数组使用了空间,双向队列使用了。
参考:
简化版:
参考: