给定一个数组和滑动窗口的大小,找出全部滑动窗口里数值的最大值。例如,若是输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有如下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。python
用一个双端队列保存滑动窗口最大值,保证里面的元素顺序是从大到小的,若是当前入队元素小于队列前一个数值,就入队,由于一会窗口滑出可能这个小的就变成了最大值,
可是若是当前元素大于以前的元素,说明以前元素已经不是窗口内最大得了,就把前一个元素出队,一直到队空或者有元素大于当前元素,入队当前元素。这样队列里第一个元素永远都是最大的。
这里队列里保存的元素下标,而不是真正的数值,能够用下标来判断窗口大小。超出窗口大小就要滑出一部分数值。c++
c++:web
class Solution { public: vector<int> maxInWindows(const vector<int>& num, unsigned int size) { deque<int>dq; vector<int>res; for(unsigned int i=0;i<num.size();++i){ while((!dq.empty())&&num[dq.back()]<=num[i]) dq.pop_back(); while((!dq.empty())&&i-dq.front()+1>size)//不能够用dq.size>size,滑动窗口能够删掉了中间结点 dq.pop_front(); dq.push_back(i); if(i>=size-1) res.push_back(num[dq.front()]); } return res; } };
python:数组
def maxInWindows(num, size):# 按照行求滑动窗口 """ maxqueue用来保存当前最大值的【索引】,这里保存索引主要为了和当前位置对比,能够计算出是否超出窗口大小,超出就弹出; """ maxqueue = [] maxlist = [] n = len(num) if n == 0 or size == 0 or size > n: return maxlist for i in range(n): # 滑出窗口队首出队 if len(maxqueue) > 0 and i - size >= maxqueue[0]: maxqueue.pop(0) # 每超出窗口只要比队尾小就存进去,比队尾大就出队 while len(maxqueue) > 0 and num[i] > num[maxqueue[-1]]: maxqueue.pop() maxqueue.append(i) if i >= size - 1: maxlist.append(num[maxqueue[0]]) return maxlist
用一个二维滑动窗口在一个矩阵上滑动,找到每一个窗口的最大值,求这个矩阵或这些最大值的和
如:n =4,m=5,a=3, b=3,n和m为行列,a和b行列窗口大小,矩阵计算方式是 (i*j) mod 10, 矩阵为:[[1 2 3 4 5], [2 4 6 8 0], [3 6 9 2 5], [4 8 2 6 0]]
滑窗结果为:[[9, 9, 9],[9, 9, 9]],和为 54。app
其实就是计算机视觉里的最大池化
1.直接用切片实现复杂度高
2.还用队列实现,先在行上作滑窗,用获得的结果在列上滑窗。svg
import numpy as np n =4 m =5 a =3 b =3 # [[0, 0, 0, 0, 0], # [0, 1, 2, 3, 4], # [0, 2, 4, 6, 8], # [0, 3, 6, 9, 2]] # 4 8 # 6 9 nums = [[0 for j in range(m)] for i in range(n) ] #print(nums) for i in range(n): for j in range(m): nums[i][j] = (i+1)*(j+1)% 10 #从1开始 res = 0 nums = np.array(nums) # 转化成numpy矩阵才能多维度切片 #print(nums) for i in range(0, n-a+1): for j in range(0, m-b+1): res += np.max(nums[i:i+a, j:j+b]) #print('*'*10) #print(res) #print(res.dtype) print(res)
def maxInWindows(num, size):# 按照行求滑动窗口 """ maxqueue用来保存当前最大值的【索引】,这里保存索引主要为了和当前位置对比 能够计算出是否超出窗口大小,超出就弹出; """ maxqueue = [] maxlist = [] n = len(num) if n == 0 or size == 0 or size > n: return maxlist for i in range(n): # 滑出窗口队首出队 if len(maxqueue) > 0 and i - size >= maxqueue[0]: maxqueue.pop(0) # 每超出窗口只要比队尾小就存进去,比队尾大就出队 while len(maxqueue) > 0 and num[i] > num[maxqueue[-1]]: maxqueue.pop() maxqueue.append(i) if i >= size - 1: maxlist.append(num[maxqueue[0]]) return maxlist def maxInWindowsCol(num, size, n, m):#按照列求滑动窗口 maxlist = [] res = 0 if n == 0 or size == 0 or size > n: return 0 maxlist = [[] for i in range(n-size+1)] for i in range(m): #列 maxqueue = [] k = 0 # 列下标 for j in range(n): #行 if len(maxqueue) > 0 and j- size >= maxqueue[0]: maxqueue.pop(0) while len(maxqueue) > 0 and num[j][i] > num[maxqueue[-1]][i]: maxqueue.pop() maxqueue.append(j) if j >= size - 1: # maxlist.append(num[maxqueue[0]][i]) res += num[maxqueue[0]][i] # print('k',k, 'num',num[maxqueue[0]][i]) maxlist[k].append(num[maxqueue[0]][i]) k += 1 return maxlist, res #print(maxInWindows([1,2,3,4,5],3)) def main(): n =4 m =5 a =3 b =3 nums = [[0 for j in range(m)] for i in range(n)] #print(nums) #初始化数组 for i in range(n): for j in range(m): nums[i][j] = (i+1)*(j+1)% 10 #从1开始 #print(nums) res = 0 # 先按行求 newnums=[] for i in range(n): newnums.append(maxInWindows(nums[i], a)) #print(maxInWindows(nums[i],a)) # 再用按行求获得结果按列求 print(maxInWindowsCol(newnums, b, n, m-a+1)) # 行没变,列变成m-a+1 if __name__ == '__main__': main()