面试题: 怎么求出一个2维矩阵中,子矩阵最大的元素之和
面试题: 如何求出一个2维矩阵中,子矩阵最大的元素之和?本帖最后由 u011493015 于 2013-07-31 13:50:39 编
面试题: 如何求出一个2维矩阵中,子矩阵最大的元素之和?
本帖最后由 u011493015 于 2013-07-31 13:50:39 编辑 今天被问到了这道题。这道题分为两个部分:
(1) 如何求一个数组中最大的子数组的和?
这一问比较简单,网上都讨论的比较多了。我很快写出了程序代码。一次遍历数组就行了O(n),空前需要N(2)
int f(int* pi,size_t num){
int sum=0;
int cur=0;
for(size_t i=0;i<num;++i)
{
cur+=pi[i];
if(cur<0)
{
cur=0;
}
if(sum<cur)
{
sum=cur;
}
}
return sum;
}
int main(int argc, char * argv[])
{
int buf[]={2,-1,3,9,-2,1,3,-1};
int s=f(buf,sizeof(buf)/sizeof(int));
return 0;
}
结果是s=15
(2) 根据(1)的思路,如何求出一个2维矩阵中,子矩阵最大的元素之和?
例如有矩阵:
1 3 -7 9
2 7 8 2
1 9 4 -1
-3 1 -5 2
非常明显,元素之和最大的子矩阵是:
2 7 8
1 9 4
那么元素和是31
如何能用最佳的方法求得31呢?
显然,用穷举的方法可以,但是这需要O(n^3)的计算复杂度。既然第(1)问可以用O(n)来解决,那么本问题是否可以用O(n^2)或者更好的方式解决?
如何设计这样的一个算法?
[解决办法]O(n^3)有,而且我知道的最好办法也就是这个复杂度。思想很简单,枚举矩形的起始行和终止行,然后做一个辅助数组A,A[i]是原数组从起始行到终止行的第i列所有数的和。然后对A做你之前发的那个线性最大。每个A本身可以用线性时间做出来。总共有O(n^2)个起始/终止行的组合。所以O(n^3)。
[解决办法]每个起始/终止行的组合都有自己的一个A。我只是懒的打字了。其实这个数组应当标记为A[i,j,k],然后对于A[i,j,0]~A[i,j,n-1]来做线性算法。