面试题 17.24. 最大子矩阵
时间复杂度: O ( m 2 ∗ n ) O(m^2*n) O(m2∗n)
先求二维数组的前缀和。以方便以 O ( 1 ) O(1) O(1)的时间求得任意矩形的和。
如果暴力枚举就是 O ( m 2 ∗ n 2 ) O(m^2*n^2) O(m2∗n2)。
思考如果这个矩阵仅仅是一个一维数组怎么办?这就是一个非常经典的最大子串和 的题目,可以在线性时间复杂度解决。
然后枚举矩阵的(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;
}
};