阅读量:0
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,复杂度为NNMM
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]谁更大,维护一下最大值即可,那么复杂度降低为MM*N,可以AC
3.代码
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; } };