leetcode面试题17.最大子矩阵

sooooooo long没刷题了,汗颜

题目链接:leetcode面试题17

1.题目

给定一个正整数、负整数和 0 组成的 N × M 矩阵,编写代码找出元素总和最大的子矩阵。

返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵,返回任意一个均可。

n,m<-200

2.分析

1)最初想到的版本:

首先f[i][j][0]表示第i行前j个格子的前缀和,f[i][j][1]表示第j列前i个格子的前缀和,那么以len1,len2,col1,col2为左上角和右下角的矩阵的子矩阵和为:f[len2][col2][2]-f[len2][col1-1][2]-f[len1-1][col2][2]+f[len1-1][col1-1][2];但这样我们就需要枚举len1,len2,col1,col2,复杂度为NN MM
2)在此基础上优化,我们可以发现,在确定了len1,len2,col1时,我们只需要使得f[len2][col2][2]-f[len1-1][col2][2]最大即可,那么我们把col1从n-1->0枚举的过程中可以逐步去比较当前最大的f[len2][col2][2]-f[len1-1][col2][2]和当col2=col1时的f[len2][col2][2]-f[len1-1][col2][2]谁更大,维护一下最大值即可,那么复杂度降低为M
M*N,可以AC

3.代码

cpp 复制代码
class Solution {
public:
    int f[210][210][5];
    static bool mycmp(vector<int> x,vector<int> y){
        return x[0]>y[0];
    }
    int get_sum(int len1,int len2,int col1,int col2){
        return f[len2][col2][2]-f[len1-1][col2][2];
    }
    vector<int> getMaxMatrix(vector<vector<int>>& matrix) {
        memset(f,0,sizeof(f));
        int m=matrix.size(),n=matrix[0].size();
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++){
                int len=i+1,col=j+1,c=matrix[i][j];
                f[len][col][0]=f[len-1][col][0]+c;
                f[len][col][1]=f[len][col-1][1]+c;
                f[len][col][2]=f[len-1][col-1][2]+f[len][col-1][1]+f[len-1][col][0]+c;
            }
        int ans=matrix[0][0],r1=0,r2=0,c1=0,c2=0;
        for(int i=0;i<m;i++)
            for(int k=i;k<m;k++){
                int len1=i+1,len2=k+1,col2=n;
                int col_sum=f[len2][col2][2]-f[len1-1][col2][2];
                for(int j=n-1;j>=0;j--)
                {
                    int col1=j+1;
                    if(get_sum(len1,len2,col1,j+1)>col_sum){
                        col_sum=get_sum(len1,len2,col1,j+1);
                        col2=j+1;
                    }
                    int ans_test=f[len2][col2][2]-f[len2][col1-1][2]-f[len1-1][col2][2]+f[len1-1][col1-1][2];
                    if(ans_test>ans){
                        ans=ans_test;
                        r1=i,c1=j,r2=k,c2=col2-1;
                    }
                }
            }
        vector<int> ans_vec;
        ans_vec.push_back(r1);
        ans_vec.push_back(c1);
        ans_vec.push_back(r2);
        ans_vec.push_back(c2);
        return ans_vec;
    }

};
相关推荐
FogLetter12 分钟前
微信红包算法揭秘:从随机性到产品思维的完美结合
算法
BUG收容所所长38 分钟前
二分查找的「左右为难」:如何优雅地找到数组中元素的首尾位置
前端·javascript·算法
itsuifengerxing1 小时前
python 自定义无符号右移
算法
猎板PCB厚铜专家大族2 小时前
高频 PCB 技术发展趋势与应用解析
人工智能·算法·设计规范
dying_man2 小时前
LeetCode--24.两两交换链表中的结点
算法·leetcode
yours_Gabriel2 小时前
【力扣】2434.使用机器人打印字典序最小的字符串
算法·leetcode·贪心算法
Psycho_MrZhang2 小时前
高等数学基础(矩阵基本操作转置和逆矩阵)
线性代数·矩阵
草莓熊Lotso3 小时前
【数据结构初阶】--算法复杂度的深度解析
c语言·开发语言·数据结构·经验分享·笔记·其他·算法
KyollBM3 小时前
【CF】Day75——CF (Div. 2) B (数学 + 贪心) + CF 882 (Div. 2) C (01Trie | 区间最大异或和)
c语言·c++·算法
CV点灯大师3 小时前
C++算法训练营 Day10 栈与队列(1)
c++·redis·算法