参考《程序员面试指南:IT名企算法于数据结构题目最优解(第2版)》
双端队列deque
普通的队列是先入先出FIFO(First In First Out),只能从队尾添加元素,从队首弹出元素。而双端队列则是从队尾添加元素,但是既可以从队首弹出元素,和普通的队列一样,也可以和栈一样从队尾弹出元素,所以叫双端队列deque(double-ended queue),它同时具备队列(FIFO)和栈(LIFO)的特性。
生成窗口最大值数组
题目描述
有一个整型数组
arr
和一个大小为w
的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。如果数组长度为n
,窗口大小为w
,则一共产生n-w+1
个窗口的最大值。请实现一个函数。
● 输入:整型数组arr
,窗口大小为w
。
● 输出:一个长度为n-w+1
的数组res
,res[i]
表示每一种窗口状态下的最大值。
示例:
输入:arr = [4,3,5,4,3,3,6,7]
,w = 3
输出:res = [5,5,5,4,6,7]
暴力解法
时间复杂度为 O ( N × w ) \mathcal{O}(N\times w) O(N×w),遍历arr
,每次统计w
窗口中的最大值即可。
双端队列解法
时间复杂度为 O ( N ) \mathcal{O}(N) O(N)。
大致思路是维护一个从队首到队尾单调递减的双端队列qmax
,其中存放着arr
中的下标,还有一个res
数组。
遍历到arr[i]
时qmax
的更新规则为:
- 如果
qmax
为空,则直接将i
放入队尾; - 如果
qmax
不为空,则需要判断队尾元素j
对应arr[j]
与当前元素的大小:
1). 如果arr[j] <= arr[i]
,则弹出j
,继续更新规则;
2). 如果arr[j] > arr[i]
,则直接将i
添加进队尾。 - 如果
qmax[0] == i - w
,则说明队首元素不再位于w