在思考这个问题时,我发现了一个在O( m_n )时间内工作的算法,如果卷积2d数组是m_n的话。
看看怎么做。在一维情况下,我们需要在数组中的大小为k的每一个窗口中找到最大值的答案。用德克。有关更多详细信息,请参见此https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/
假设在二维情况下k是滤波器的大小,步长为10填充,n*m矩阵。
Step1,然后计算所有大小窗口的最大值k,给出了每行大小k的最大窗口的答案。在计算完所有行之后。
在转换矩阵中的Step2之后,对于大小为k的滑动窗口中最大的列,对修改后的矩阵中的每一列做同样的操作。在重复之后,在矩阵的位置i,j开始于单元格i,j作为左上角,i+k-1,j+k-1作为右下角,得到大小为k*k的整个子数组的最大值。
证据很简单。
当你有最大的k行,那么在一个大小窗口中计算最大值时,k在列上给出了整个矩阵上的最大值。
示例
5 3 2 1 4
2 3 1 5 3
1 2 3 4 6
1 2 3 4 5
5 4 3 2 1
假设n=5,m=5和k=3。
修改后的矩阵看起来
5 3 4
3 5 3
3 4 6
3 4 5
5 4 3
进一步应用step2看起来就像。
5 5 6
3 5 6
5 4 6
这就是我们面前的最大集合层。
这是一个很好的算法,可以给CNN模型带来优化,还是有更好的现有算法?请发表你的意见?
发布于 2022-04-06 07:46:21
2 Time池最佳时间复杂度为O(nm)
以下是我的C++代码:
#include <iostream>
#include <vector>
#include <deque>
#include <cstring>
using namespace std;
typedef long long LL;
const int N = 1e3;
int g[N][N];
void max_window(int l1, int l2, int r1, int r2, int k) {
    vector<int> nums;
    // Time: max(n, m)
    for (int i = l1; i <= r1; i ++) {
        for (int j = l2; j <= r2; j ++) {
            nums.push_back(g[i][j]);
        }
    }
    vector<int> res;
    deque<int> q;
    for (int i = 0; i < nums.size(); i ++) {
        while (q.size() && i - q.front() >= k) q.pop_front();
        while (q.size() && nums[q.back()] <= nums[i]) q.pop_back();
        q.push_back(i);        
        if (i >= k - 1) res.push_back(nums[q.front()]);
    }
    int cnt = 0;
    for (int i = l1; i <= r1; i ++) {
        for (int j = l2; j <= r2; j ++) {
            if (cnt >= res.size()) break;
            g[i][j] = res[cnt];
            cnt ++;
        }
    }
    return;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    #endif
    int n, m, a, b;
    cin >> n >> m >> a >> b;
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < m; j ++) {
            cin >> g[i][j];
        }
    }
    for (int i = 0; i < n; i ++) {
        for (int j = 0; j < m; j ++) {
            cout << g[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
    // shape: n x m
    for (int i = 0; i < n; i ++) {  
        max_window(i, 0, i, n - 1, b);
    }
    for (int j = 0; j < m - b + 1; j ++) {  // shape:n x (m - b + 1)
        max_window(0, j, m - 1, j, a);
    }
    // shape:(n - a + 1) x (m - b + 1)
    for (int i = 0; i < n - a + 1; i ++) {
        for (int j = 0; j < m - b + 1; j ++) {
            cout << g[i][j] << " ";
        }
        cout << endl;
    }
    
    return 0;
}输入:
5 5 3 3
5 3 2 1 4
2 3 1 5 3
1 2 3 4 6
1 2 3 4 5
5 4 3 2 1输出:
5 3 2 1 4 
2 3 1 5 3
1 2 3 4 6
1 2 3 4 5
5 4 3 2 1
5 5 6
3 5 6
5 4 6顺便说一句,这里是最佳时间复杂度为O(n)的一维最大池示例。https://leetcode.com/problems/sliding-window-maximum/
https://stackoverflow.com/questions/66924060
复制相似问题