最大子矩阵和

参考来源:

https://blog.csdn.net/fengyingjie2/article/details/54427146

https://blog.csdn.net/kavu1/article/details/50547401

 

题目:

给定一个矩阵,都是整数,其中(n≤500),求出其中的最大子矩阵

解题思路:

O(n^2*n^2*n^2)的做法:

很容易想到,可以枚举一个矩阵的左上角和右下角的坐标确定这个矩阵,然后,再用两个循环进行统计

O(n^2*n^2)的做法:

对于上面的方法,提前处理一个前缀和,即可省去后面统计的时间复杂度。

正解,即O(n³)事实上并没有这么多

想要做对这道题,我们先要明白一个最大子段和算法的做法:

例如数字a={8,-2,3,-11,5},我们需要求出一段连续数字的最大和是什么

我们的思想是DP

设f[i]表示从1~i这些位置中的最大子段和

如何转移?对于当前的点i,我们只有两种状态,选择与上一个子段和连接或者自己重新构成一个子段和。

若选,则与1~i-1的最大子段和有关系,即1~i-1的最长子段和加上当前的a[i],重新构成一个子段和

若不选,则与1~i-1最大子段和没有关系,自己重新构成了一个子段和

两者取较大者,即可解决

列出状态转移方程:f[i]:=max(a[i],f[i-1]+a[i])

时间复杂度 O(n)


 

 

说了这么多都是铺垫,下面是重点:

为了能够在原始矩阵里很快得到从 i 行到 j 行 的上下值之和,我们这里用到了一个辅助矩阵,它是原始矩阵从上到下加下来的。
假设原始矩阵是matrix, 它每一层上下相加后得到的矩阵是total,那么我们可以通过如下代码实现:

int[][] total = matrix;    
for (int i = 1; i < matrix[0].length; i++) {    
    for (int j = 0; j < matrix.length; j++) {    
    total[i][j] += total[i-1][j];    
    }    
}    

如果我们要求第 i 行到第 j 行之间上下值的和,我们可以通过total[j][k] - total[i-1][k] 得到, k 的范围从1 到 matrix[0].length - 1。
有了这些知识点,我们只需要在所有的情况下,把它们所对应的局部最大子矩阵进行比较,就可以得到全局最大的子矩阵。代码如下:

 1 public int subMaxMatrix(int[][] matrix) {    
 2             
 3         int[][] total = matrix;    
 4         for (int i = 1; i < matrix[0].length; i++) {    
 5             for (int j = 0; j < matrix.length; j++) {    
 6                 total[i][j] += total[i-1][j];    
 7             }    
 8         }    
 9             
10         int maximum = Integer.MIN_VALUE;    
11         for (int i = 0; i < matrix.length; i++) {    
12             for (int j = i; j < matrix.length; j++) {    
13                 //result 保存的是从 i 行 到第 j 行 所对应的矩阵上下值的和    
14                                 int[] result = new int[matrix[0].length];    
15                 for (int f = 0; f < matrix[0].length; f++) {    
16                     if (i == 0) {    
17                         result[f] = total[j][f];    
18                     } else {    
19                         result[f] = total[j][f] - total[i - 1][f];    
20                     }    
21                 }    
22                 int maximal = maxSubsequence(result);    
23                     
24                 if (maximal > maximum) {    
25                     maximum = maximal;    
26                 }    
27             }    
28         }    
29             
30         return maximum;    
31     }   

 

posted on 2018-03-31 22:53  华山青竹  阅读(7250)  评论(0编辑  收藏  举报

导航