【完虐算法系列】「字符串 – 滑动窗口」复盘总结 (3)

滑动窗口最大值是一道典型的滑动窗口的例题。该题被标记为困难,可能就在于最大值的判断,如果使用传统方式的话,时间复杂度就会很高。

关于最大值,可是尝试使用优先队列去解决,即构造大顶堆,也可以使用双向队列解决问题。

以下用两种方式都来解决一下。

方法一:优先队列解决

由于题目要求是选择窗口内的最大值,因此需要构造了大顶堆,此时得出来队首元素就是整个队列的最大值。

注意点:我们这里由于采用 Python 的 heapq 库来实现,而 heapq 库只能构造小顶堆。

因此,可以换一个思路进行实现,例如列表 [1,-3,12]:

首先,每个元素的负值都插入到优先队列中,构造小顶堆,产生的结果是这样的 [-12, 3, -1]

然后,将队首元素去除并且取反,得到的结果是 12。这就是我们想要的结果,取到了其中的最大值。

关于 Python 使用优先队列的方式,可以查看这一篇文章【https://mp.weixin.qq.com/s/94Rnnt7R5_kTfoAW0j-wyQ】,有详细的使用方式。

首先,初始化一个窗口大小的优先队列 window,并且记录元素(注意这里要取反)以及元素下标,组装成一个元祖 (-num, index)。

然后,当不断向右移动窗口,把新加进来的元素(元祖)加入到优先队列中。

最后,判断当前优先队列中的队首元素对应的 index,是否在固定窗口内,如果在,则取值并且取反;否则,删除队首元素,继续判断。

下面依旧用几个图清晰的一步一步操作:

我们用字符串为 nums=[12, -3, 1, -1, 9, 5], k = 3 来进行说明。

初始化 res 用来存储每个窗口最大值。

① 初始化优先队列 window=[(-12, 0), (3, 1), (-1, 2)],判断队首元素的下标值 value=0 在当前窗口内。

所以,取出队首元素-12,并且取反,res=[12]

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

② 优先队列 window=[(-12, 0), (-1, 2), (1, 3), (3, 1)],判断队首元素的下标值 value=0 不在当前窗口内,弹出队首元素。

此时,window=[(-12, 0), (-1, 2), (1, 3), (3, 1)],再判断此时队首元素的下标值 value=2 在当前窗口内。

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

所以,取出队首元素-1,并且取反,res=[12, 1]

③ 优先队列 window=[(-9, 4), (-1, 2), (3, 1), (1, 3)],判断队首元素的下标值 value=4 在当前窗口内。

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

所以,取出队首元素-9,并且取反,res=[12, 1, 9]

④优先队列 window=[(-9, 4), (-5, 5), (3, 1), (1, 3), (-1, 2)],判断队首元素的下标值 value=4 在当前窗口内。

【完虐算法系列】「字符串 – 滑动窗口」复盘总结

所以,取出队首元素-9,并且取反,res=[12, 1, 9, 9]

这个时候就都所有取数完成了!

中间关于 Python 的 hepq 库构造大顶堆有点绕,这点稍微理解下,对于后面的解题帮助特别大。

思路描述完了,再看下代码实现:

def maxSlidingWindow(self, nums, k): size = len(nums) window = [(-nums[i], i) for i in range(k)] heapq.heapify(window) res = [-window[0][0]] for i in range(k, size): heapq.heappush(window, (-nums[i], i)) while window[0][1] <= i-k: heapq.heappop(window) res.append(-window[0][0]) return res

感觉描述了一堆,但是代码倒是很简洁。

说完方法一,下面看看方法二...

方法二:双向队列解决

为什么要使用双向队列呢?在算法执行过程中,需要两边进行入队和出队的操作。

大致思路也比较容易:

首先,初始化一个空队列 queue;

然后,逐个入队,但当下一个元素入队时,判断与队尾元素大小。如果小于队尾元素,则入队。否则,队尾依次出队,直到大于要入队的元素;

最后,判断队首元素是否是在窗口内,如果在窗口内,直接取值,否则,队首元素出队。

下面依旧用几个图清晰的一步一步操作:

① 元素 12 入队;窗口范围 [0, 0]

未形成窗口,不取值;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgddzg.html