给定一个长度为n的一维的数组matrix[n],让求其最大matrix[i] + matrix[i+1] + ... + matrix[j] = sum问题?
简单算法:
穷举法
先预处理map[n]表示从matrix[0]->matrix[n]的和
for(int i = 0 to n)
for(int j = i+1 to n)
{
int tmp = map[j] - map[i-1];
}
算法时间复杂度为O(n^2).
空间额外占据O(n)。
DP算法:
设max[j]为matrix[0....j]中的最大子段之和,max[j]当前只有两种情况:
1)最大子段一直连续到matrix[j]; (2)以matrix[j]为起点的子段。
注意!
如果当前最大子段没有包含matrix[j],如果没有包含的话,在算max[j]之前我们就已经算出来了。
得到max[j]的状态转移方程为:max[j] = max { max[j-1] + matrix[j], matrix[j]}
所求的最大子段和为max{ max[j], 0<=j<n}
进一步,我们可以将max[]数组用一个变量代替。因为每次计算max[i]之需要用到上一个max[i-1],故一个变量可以替代。
空间优化至O(1)
max = - (1<<31);
tmp = 0;
for(int i=1 to n)
{
if(tmp>0)
tmp += matrix[i];
else
tmp = matrix[i];
if(tmp>max)
max = tmp;
}
--------------------------------------------------------------
给定一个二维的数组matrix[n][n],让求其最大子矩阵和问题?
原始算法:
遍历每一个子矩阵,左上角为[x,y],右下角为[c, r],可知子矩阵共有O(n^4);
而每个子矩阵算总和的算法复杂度为O(n^2);
---->原始算法复杂度为o(n^6),时间复杂度太高,但是却无额外空间。
改进算法二:
遍历每一个子矩阵,左上角为[x, y],右下角为[c, r],子矩阵共有O(n^4);
但是每个子矩阵算和,时间复杂度可以优化为O(1)。
利用到额外空间map[n][n],其中map[x][y]表示左上角为[0, 0],右下角为[x, y]的子矩阵和。
左上角为[x, y],右下角为[c, r],子矩阵的和 = map[c][r] - map[x-1][r] - map[x][r-1] + 2*map[c-1][r-1]。
时间复杂度总共为O(n^4);
额外空间O(n^2)。
改进算法三:
利用额外空间O(n^3),记录子矩阵map[i][j][y],第y列的第i行到第j行的和。
1)以i行开始,j行结束的子矩阵,总共有n个。计算每个子矩阵的算法复杂度为O(1)。
2)i行开始,j行结束。2变量,两个变量,复杂度为O(n^2)。
可知该算法可以用O(n^3)的时间复杂度算出,但其代价是空间复杂度也是O(n^3)。
改进算法四:
相比算法三,仅是优化了空间复杂度,将其降低为O(n^2)。
子矩阵和map[x][y]表示第y列从第1行到第i行的和。
算法三的map[i][j][k] = map[j][k] - map[i-1][k]即可。不用都记录下来
参考:
http://www.360doc.com/content/10/0423/13/1283481_24497771.shtml
http://blog.163.com/quxp0718@126/blog/static/9693793820097308375933/