LeetCode 239. 滑动窗口最大值&二维滑动窗口

滑动窗口最大值

题目描述

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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]}。

思路

用一个双端队列保存滑动窗口最大值,保证里面的元素顺序是从大到小的,如果当前入队元素小于队列前一个数值,就入队,因为一会窗口滑出可能这个小的就变成了最大值,
但是如果当前元素大于之前的元素,说明之前元素已经不是窗口内最大得了,就把前一个元素出队,一直到队空或者有元素大于当前元素,入队当前元素。这样队列里第一个元素永远都是最大的。
这里队列里保存的元素下标,而不是真正的数值,可以用下标来判断窗口大小。超出窗口大小就要滑出一部分数值。

code

c++:

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。

思路

其实就是计算机视觉里的最大池化
1.直接用切片实现复杂度高
2.还用队列实现,先在行上做滑窗,用得到的结果在列上滑窗。

code
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()
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\],可以使用暴力解法来求解滑动窗口最大值。具体的做法是,遍历数组,对于每个窗口,使用一个内部循环来找到窗口中的最大值,并将其存储在结果数组中。时间复杂度为O(n*k),其中n为数组长度,k为窗口大小。 根据引用\[2\],还可以使用队列来求解滑动窗口最大值。具体的做法是,使用一个双端队列来维护一个单调递减的窗口。遍历数组,对于每个元素,首先判断队头是否在滑动窗口范围内,如果不在,则将其从队头移除。然后,将当前元素与队尾元素比较,如果当前元素大于队尾元素,则将队尾元素移除,直到队列为空或者当前元素小于等于队尾元素。最后,将当前元素的索引插入队尾。如果滑动窗口的元素个数达到了k个,并且始终维持在窗口中,就将队头元素加入答案数组中。时间复杂度为O(n),其中n为数组长度。 综上所述,可以使用暴力解法或者使用队列来求解leetcode滑动窗口最大值。 #### 引用[.reference_title] - *1* *3* [leetcode239. 滑动窗口最大值](https://blog.csdn.net/kkkkuuga/article/details/124829581)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode#239. 滑动窗口最大值 (Java解法)](https://blog.csdn.net/paranior/article/details/114890555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值