给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
窗口大于数组长度或窗口长度为 0 的时候,返回空。
思路1:优先队列
使用优先队列(堆)维护窗口内的最大值;
细节:
堆除了要保存值还要保存索引, 用于判断当前的最大值是否还在窗口内;
Python 中的默认实现为最小堆, 需要转成最大堆(取相反数);
Python
classSolution:defmaxInWindows(self,arr: List[int],size:int) -> List[int]:if size <=0or size >len(arr):return []import heapq# 初始化大顶堆 h = []for i inrange(size): heapq.heappush(h, (-arr[i], i))# 默认小顶堆,取相反数使变成大顶堆 ret = [-h[0][0]]for i inrange(size, len(arr)):while h and h[0][1] <= i - size:# 保证堆顶元素在窗口内 heapq.heappop(h) heapq.heappush(h, (-arr[i], i)) ret.append(-h[0][0])return ret
思路2:单调队列
使用一个严格单调队列 q 保存窗口内值的索引(保存索引,相当于保存了两个信息);
这样每次将队首元素加入结果集即可;当队首元素不在窗口中时,出队;
Python
classSolution:defmaxInWindows(self,arr: List[int],size:int) -> List[int]:# 窗口大于数组长度时if size >len(arr):return []from collections import deque# 初始化单调队列,严格单调 q =deque()for i inrange(size):# 当入队元素大于队尾时,队尾出队while q and arr[q[-1]]<= arr[i]:# 这里用 <= 是避免相等时判断 q.pop() q.append(i)# 队列中保存 索引 而不是值,这样相当于保存了两个信息 ret = [arr[q[0]]] # 初始化结果序列for i inrange(size, len(arr)):# 如果队首不在窗口内,则弹出(保存索引的好处)if q[0]== i - size: q.popleft()# 保持单调队列while q and arr[q[-1]]<= arr[i]: q.pop() q.append(i) ret.append(arr[q[0]])return ret