窗口内最大值的更新结构
#双端队列,双向链表结构,从头到尾从大到小
#加数:没有直接进;小于原来,直接进;大于原来,弹出数,直到找到该数的位置,进入
#减数:看头部下标是否过期,出窗口,没过期,不动
#窗口最大值即为头部最大值
from collections import deque
def maxwindow(nums,k):
if k==1:
return nums
qq=deque([])#创建队列
qq.append(0)#将0加入
res=[]
for x,y in enumerate(nums[1:],1): #x,y存储当前元素的下标和nums值,从位置1开始
if nums[qq[-1]]<=y: #如果当前数比队尾元素大,弹出
for i in range(len(qq)-1,-1,-1):
if nums[qq[i]]>y:
break
else:
qq.pop()
qq.append(x) #加入当前数
if qq[0]<=x-k: #若队头元素过期,弹出队头元素
qq.popleft()
if x>=k-1: #若是一个完整窗口,更新结果列表res
res.append(nums[qq[0]])
return res
arr=[1,2,4,2,6,2]
print(maxwindow(arr,3))
另一种写法:
队列中只存下标
from collections import deque
def maxwindow(nums,w): #w为窗口大小
queue=deque()
res=[]
for i in range(len(nums)):
while queue and nums[queue[-1]]<=nums[i]:
queue.pop()
queue.append(i)
if queue[0]==i-w: #过期,弹出
queue.popleft()
if i>=w-1:
print(queue)
res.append(nums[queue[0]])
return res
nums=[1,2,3,8,4,2,6,7]
print(maxwindow(nums,3))
应用:
最大值-最小值<num的子数组数量
窗口最大值、最小值更新结构
l-r若满足条件,往里缩肯定满足条件,往外扩肯定不满足条件
从0开始找到每个位置满足条件的子数组数量
from collections import deque
def alllessnum(arr,num):
qmin=deque()
qmax=deque()
l=0
r=0
res=0
while l<len(arr):
while r<len(arr):
while qmin and arr[qmin[-1]]>=arr[r]: #最小值更新结构
qmin.pop()
qmin.append(r)
while qmax and arr[qmax[-1]]<=arr[r]: #最大值更新结构
qmax.pop()
qmax.append(r)
if arr[qmax[0]]-arr[qmin[0]]>num: #扩到不达标的位置
break
r+=1
if qmin[0]==l: #判断过不过期
qmin.popleft()
if qmax[0]==l: #判断过不过期
qmax.popleft()
res+=r-l #每个位置满足条件的子数组个数
l+=1
return res