题目:给定一个矩阵matrix,其中的值有正,有负,有0,返回子矩阵的最大累加和
例:matrix为:
-1 -1 -1
-1 2 2
-1 -1 -1
其中最大累加和的子矩阵为
2 2
所以返回4.
分析思路:
下面有方框圈出来的类似这种的都是子矩阵
- 刚开始考虑用暴力解法
将每一个定点都进行遍历找子矩阵,虽然可行,但是它的时间复杂度会非常高0(n^4)。
改进算法的时间复杂度为0(n^3)
改进它的加法交换律
原暴力解法
例如:需要累加4次
- 改进之后:先将每列累加再一起相加
以第一行的第一个-1为开头,之后想到把它们先对每一列求和,上面依次就是-3 0 0
最大的子矩阵累加和为0 0,对应后两列;
下一次再以其他行元素为开头,将所有矩阵都遍历一遍
例如:以第二行的第一个元素-1为开头,单独的取第二行,发现最大的累加和就是4,对应的子矩阵就是2 2;
继续以其他行元素为开头,把所有符合要求的子矩阵都遍历一遍,以第二行或第三行为开头,
以第一行第一个元素开头,有3行可以遍历;(行数1;1,2;1,2,3)
以第二行第一个元素开头,有2行可以遍历;(行数2;2,3)
以第三行第一个元素开头,有1行可以遍历;(行数3)
一共n^2.
- 代码:
package maxsumju;
import java.util.Arrays;
public class Maxsum {
private static int beginrow;
public static void main(String[] args) {
int[][] maxju= {
{-90,48,78},
{64,-40,64},
{-81,-7,66}
};
int res=maxsum(maxju);
System.out.println(res);
}
//N^3时间复杂度
private static int maxsum(int[][] maxju) {
int beginrow=0; //以它为起始行
final int M=maxju.length;
final int N=maxju[0].length;
int[] sums=new int[N]; //按列求和
int max=0; //历史上最大的子矩阵和
while(beginrow<M) { //起始行
for(int i=beginrow;i<M;i++) { //从起始行到第i行
//按列累加
for(int j=0;j<N;j++) {
sums[j]+=maxju[i][j];
}
//累加完成
//求出sums的最大和子数组O(n)
static void findByForce(int[] arr) {
int sums=arr[0]; //前j个元素累加和
int max=sums;
if(sums>max) {
max=sums;
}
Arrays.fill(sums, 0); //快速地将suns的每个元素都设定为0
beginrow++;
}
return max;
}
}