【滑动窗口】【单调队列】个人练习-Leetcode-2373. Largest Local Values in a Matrix
题目链接:https://leetcode.cn/problems/largest-local-values-in-a-matrix/
题目大意:给出一个N*N
矩阵,要求做池化操作,选出每个3*3
矩阵的最大值,返回一个(N-2)*(N-2)
矩阵
思路:这是个简单题,虽然可以暴力做,但当矩阵很大并且窗口比3*3
更大时会有很多重复操作,是有改进空间的。
(1)首先我们可以对每一行维护一个单调队列q
,q
中【存储下标】,下标对应的元素是单调递减的。想象我们要找到这一行中,一个长度为3
的滑动窗口,保存最大值。如果扫描到的元素grid[i][j]
比队尾元素大,那么grid[i][j]
很明显就更适合做最大值,q
从队尾一直弹出直到【为空】【有一个元素比grid[i][j]
大】
(2)当j >= 2
以后,因为滑动窗口大小只有3
,因此可能有【弹出队首】的操作了。队首的下标对应的元素grid[i][q.front()]
是最大的,将其和结果对比,更大的话就写入。这个过程要遍历三行(k
从i-2
到i
的过程),因此用max()
函数取大。随后,因为滑动窗口大小只有3
,若队首小于等于j-2
,那么弹出。
完整代码:
class Solution {
public:vector<vector<int>> largestLocal(vector<vector<int>>& grid) {int N = grid.size();vector<vector<int>> ret(N-2, vector<int>(N-2, 0)); for (int i = 0; i < N; i++) {deque<int> q;for (int j = 0; j < N; j++) {while (!q.empty() && grid[i][j] >= grid[i][q.back()]) {q.pop_back();}q.push_back(j);if (j >= 2) {int val = grid[i][q.front()];for (int k = i-2; k <= i; k++) {if (k >= 0 && k < N-2) ret[k][j-2] = max(ret[k][j-2], val);}if (q.front() <= j-2) q.pop_front();}}}return ret;}
};