这是leetcode上的一道题,其算法之典型,可谓算法中的重中之重
我们来分析一下,反正就是用其他算法会超时,咱必须得用单调队列
下面介绍一下单调队列:
我最近学到了一个好习惯就是把算法用类封装起来,之后用对象调用:
so
我这里给出单调队列的算法:
class MonotonicQueue:#Monotonic adj.单调的
from collections import deque
#这个东西叫双向队列,也就是可以在两头操作这个东西
def __init__(self, type, sub=[]):
self.type = type == 'decrease'#逆序,或者叫单调递减 3 2 1这样
#意思是type是一个bool型变量,当他是那个字符串的时候,就是True
self.queue = self.deque()
#queue是一个空的deque
for i in sub:
self.push(i)#这个push 是下面的一个方法
def head(self):
return self.queue[0]#取头
def is_monotonic(self, x):#重点,判断插入x后是否是单调的
tail = self.queue[-1]
#首先取一下尾
return tail >= x if self.type else tail <= x
#你看,但是decrease的时候,再看x(待插入的数据)是不是比尾巴小,要是比尾巴小,那么tail >= x为真,此方法返回真
#反之,increase 的时候 ,看看x是不是比尾巴大,以维持递增
def push(self, x):
while self.queue and not self.is_monotonic(x):#意思是非空,不单调
self.queue.pop()#在队列(目前是单调的)中弹走一个数
#并且这里是while 也就是可以一直弹 ,谈到空,或者非空且单调,有点绕是吧,因为单调了后面的条件就必不满足了
self.queue.append(x)#清理干净后,也就是做完手术后,也就是前方序列单调且加入x也单调,就加x
def pop(self, value):
if self.head() == value:
self.queue.popleft()
#如果队头等于某值,弹队头,根据值的相同来弹队头进行遍历
class Solution:
def maxSlidingWindow(self, nums, k):
maxs = []
decrease_queue = MonotonicQueue('decrease', nums[: k])#看似一行,其实特麻烦
maxs.append(decrease_queue.head())
#举个例子吧
#decrease_queue此时是3,-1 maxs 是 3
for old_left in range(len(nums) - k):#0-(5—1)遍历
new_right = old_left + k
old_left = nums[old_left]
new_right = nums[new_right]
decrease_queue.pop(old_left)
decrease_queue.push(new_right)#有文章做.push方法复杂
maxs.append(decrease_queue.head())#5遍5个值,第一个单摘出来了
return maxs
if __name__=="__main__":
s = Solution()
a=[1,3,-1,-3,5,3,6,7]
b=s.maxSlidingWindow(a,3)
print(b)
前半部分我注释写的巨详细,后半部分太累了,改天写
写写心得吧,我感觉算法学习,是一个像电子跃迁的过程,我们是按能级分的,你势必从看基础知识到看懂基础知识,会看代码到看懂代码,写代码到写成代码,看似每天在努力,但是感觉自己毫无进步,其实我们的每一次努力都是为我们进行跃迁积蓄力量,当力量积蓄到一定程度的时候,突然出击,可能我们就到下一个能级了,但前提是力量足够强,突然要足够突然。