题目描述:给定一个矩阵matrix,其中有正、有负、有0,返回子矩阵的最大累加和。
例如,matrix为:
{{-1,-1,-1},
{-1 , 2 , 2},
{-1,-1,-1}}
其中最大累加和的子矩阵为:
2,2
所以返回4
解题思路
这道题的关键在于必须是子矩阵,而子矩阵的情况太多了,如果一一列举的话想必是不能达到要求的。所以这道题需要对原二维数组(矩阵)进行一些预处理,也就是降维度或压缩,方法就是对矩阵按列求和,然后按照一位数组的思想去求这个最大累加和。我之前有写过一篇一位数组解决类似问题的文章,可以去看一下。一位数组求子数组的最大累加和
有了这样的处理真的就很方便地可以解决啦
//子矩阵的最大累加和,注意:也要是连续的子矩阵
#include<iostream>
#include<cstring>
#define N 3
using namespace std;
int findMax(int arr[]);
int solve(int matrix[][N],int M){
int helper[N] = {0}; //辅助数组用于压缩
int beginRow,j,k;
int tmpMax,max=helper[0];
while(beginRow < M){
for(j = beginRow; j<M; j++){
for(k = 0; k<N; k++){ //按列求和
helper[k] += matrix[j][k];
}
//求完了就去找压缩后数列的最大值
tmpMax = findMax(helper);
if(tmpMax > max){
max = tmpMax;
}
}
memset(helper,0,N*sizeof(int)); //helper清零
beginRow++;
}
return max;
}
int findMax(int arr[]){
int sentry=0 , cursor=0 ; //定义哨兵和游标
int maxSum = arr[0]; //最大的和
int tmpSum = 0;
int end;
while(cursor < N ){
tmpSum += arr[cursor];
cursor ++;
if(tmpSum < 0){ //如果是负的,就说明是负贡献,应该调整哨兵
sentry = cursor;
tmpSum = 0; //归零
continue;
}
if(tmpSum > maxSum){
maxSum = tmpSum;
end = cursor-1;
}
}
return maxSum;
}
int main(){
int matrix[][N] = {
{-1,1,1},
{-1,2,-2},
{-1,1,1}
};
int res = solve(matrix,3);
cout<<"result: "<<res;
}
运行结果示例
时间复杂度分析
这道题的时间复杂度是O(M✖N),其中由于按列求和时beginRow要走M行,而求最大子数组累加和的时候是线性的O(N)(可以参考上一篇文章的分析)。