您的位置:首页 > 其它

学习笔记之最大子矩阵问题

2016-07-13 10:16 232 查看
首先来看看一维的最大字段和问题的解法:

    动态规划算法求解

    算法思路如下:

    记

,则所求的最大子段和为:


    由b[j]的定义知,当b[j-1]>0时,b[j]=b[j-1]+a[j],否则b[j]=a[j]。由此可得b[j]的动态规划递推式如下:

     b[j]=max{b[j-1]+a[j],a[j]},1<=j<=n。该算法的时间复杂度和空间复杂度都为O(n)。

     具体代码如下:

int maxSubArray(int[] nums){
int length = nums.length;
int sum = 0;int max = 0;
for(int i = 0;i<length;i++){
if(sum>0)
sum+=nums[i];
else
sum = nums[i];
if(sum>max)
max = sum;
}
return max;
}


接下来看一下最大子矩阵和问题:

     (1)问题描述:给定一个m行n列的整数矩阵A,试求A的一个子矩阵,使其各元素之和为最大。

     (2)动态规划法求解:

      用二维数组a[1:m][1:n]表示给定的m行n列的整数矩阵。子数组a[i1:i2][j1:j2]表示左上角和右下角行列坐标分别为(i1,j1)和(i2,j2)的子矩阵,其各元素之和记为:


      最大子矩阵问题的最优值为

。如果用直接枚举的方法解最大子矩阵和问题,需要O(m^2n^2)时间。注意到

,式中,

,设

,则


容易看出,这正是一维情形的最大子段和问题。因此,借助最大子段和问题的动态规划算法MaxSubArray,可设计出最大子矩阵和动态规划算法如下:

public int maxMatrix(int[][]nums){
int rows = nums.length;
int cols = nums[0].length;
int max = 0;
int[] b = new int[cols];
for(int i = 0;i<rows;i++){
for(int k = 0;k<cols;k++)
b[k] = 0;

for(int j = i;j<rows;j++){
for(int k = 0;k<cols;k++){
b[k] += nums[j][k];
}
int sum = maxSubArray(b);
if(sum>max)
max = sum;
}
}
return max;
}


b[k]代表i到j行第k列的值的总和,循环列数,计算出i到j行每一列的总和,得到一维数组b为选定行的列项和,此时对b进行一维数组最大子段和的计算,确定选定列。此时即可求出i到j行子矩阵的最大和。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 最大子段和