考虑一个经常碰到的问题,对于一个数组,现在有一个窗口[i, j]
,i
和j
只会做增加的操作,要求输出[i,j]
上的最小值。
这其实就是一个“最小队列(min queue)”问题:维护一个队列,使得插入、弹出、获取最小值这三个操作的平均时间复杂度都是
![equation?tex=O%281%29](https://i-blog.csdnimg.cn/blog_migrate/89d5b096d58fa794c11b5f410c6a3378.png)
实现这个的方法是使用两个队列,其中一个是单调队列。
思路参见:
滑动窗口的最小值问题_C/C++_weixin_38391092的博客-CSDN博客blog.csdn.net![f7aace991fe6a95783f5e3feaba5ffc6.png](https://i-blog.csdnimg.cn/blog_migrate/230b17642e71b910e524a8e2f13d4d3a.jpeg)
import collections
class MinQueue(collections.deque):
def __init__(self, iterable=None, maxlen=None):
super().__init__(maxlen=maxlen)
self.minQueue = collections.deque()
if isinstance(iterable, collections.abc.Iterable):
for it in iterable:
self.append(it)
@property
def minV(self):
return self.minQueue[0] if self.minQueue else None
def append(self, v):
while self.minQueue and v < self.minQueue[-1]:
self.minQueue.pop()
self.minQueue.append(v)
super().append(v)
def extend(self, iterable):
for it in iterable:
self.append(it)
def pop(self):
if not self.minQueue:
return None
v = super().popleft()
if self.minQueue[0] == v:
self.minQueue.popleft()
return v
上面用 python 对这一问题做了很好的封装。
同样的,有滑动窗口最大值
import collections
class MaxQueue(collections.deque):
def __init__(self, iterable=None, maxlen=None):
super().__init__(maxlen=maxlen)
self.maxQueue = collections.deque()
if isinstance(iterable, collections.abc.Iterable):
for it in iterable:
self.append(it)
@property
def maxV(self):
return self.maxQueue[0] if self.maxQueue else None
def append(self, v):
while self.maxQueue and v > self.maxQueue[-1]:
self.maxQueue.pop()
self.maxQueue.append(v)
super().append(v)
def extend(self, iterable):
for it in iterable:
self.append(it)
def pop(self):
if not self.maxQueue:
return None
v = super().popleft()
if self.maxQueue[0] == v:
self.maxQueue.popleft()
return v