LeetCode 面试题 17.24. 最大子矩阵 ( 二维前缀和 + 最大子串和(DP+DP) )

面试题 17.24. 最大子矩阵
时间复杂度: O ( m 2 ∗ n ) O(m^2*n) O(m2n)

先求二维数组的前缀和。以方便以 O ( 1 ) O(1) O(1)的时间求得任意矩形的和。

如果暴力枚举就是 O ( m 2 ∗ n 2 ) O(m^2*n^2) O(m2n2)
思考如果这个矩阵仅仅是一个一维数组怎么办?这就是一个非常经典的最大子串和 的题目,可以在线性时间复杂度解决。

然后枚举矩阵的(x1,.,x2,.)就相当于先确定矩形矩形的上下界,然后将这个矩形压缩成一个一维数组,就转换成一个最大子串和的问题了

这种枚举方式和下面这个题目是有异曲同工之处的。
1504. 统计全 1 子矩形

class Solution {
    
    
public:
    int m = 0, n = 0, maxSum = -1e9;
    vector<int> ans;
    vector<vector<int>> s;

    void update(int sum,int x1,int y1,int x2,int y2){
    
    
        if(sum>maxSum){
    
    
            maxSum = sum;
            ans = {
    
    x1,y1,x2,y2};
        }
    }
    
    int get(int x1,int y1,int x2,int y2){
    
    
        return s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];
    }

    vector<int> getMaxMatrix(vector<vector<int>>& a) {
    
    
        m = a.size(), n = a[0].size();
        s.resize(m+1,vector<int>(n+1,0));
        for(int i=1;i<=m;i++){
    
    
            for(int j=1;j<=n;j++){
    
    
                s[i][j] = s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i-1][j-1];
            }
        }
        for(int x1=0;x1<m;x1++){
    
    
            for(int x2=x1;x2<m;x2++){
    
    
                int cnt = get(x1+1,1,x2+1,1), last = 0;
                update(cnt,x1,0,x2,0);
                for(int y=1;y<n;y++){
    
    
                    int cur = get(x1+1,y+1,x2+1,y+1);
                    if(cnt<0) cnt = cur, last = y;
                    else cnt += cur;
                    update(cnt,x1,last,x2,y);
                }
            }
        }
        return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/qq_44846324/article/details/108409700