有一个正整数和负整数组成的NxN矩阵,请编写代码找出元素总和最大的子矩阵。请尝试使用一个高效算法。
给定一个int矩阵mat和矩阵的阶数n,请返回元素总和最大的子矩阵的元素之和。保证元素绝对值小于等于100000,且矩阵阶数小于等于200。
测试样例:
[[1,2,-3],[3,4,-5],[-5,-6,-7]],3
返回:10
思路:
1:先将二维数组纵向合并成一维数组 然后计算一维数组的最大子序列和。
2:最大一维子序列求和问题
例如数组1 2 3 -4 5 -8 7 4 2 -10
定义temp存储0~i位置的累加和
定义Max为0~i位置的最大累加和
temp初始化为0 temp与0比较 若小于零 temp = mat[i] 否则temp=+mat[i];
temp每次变化时都和max比较 若大与max则max=temp 否则 max不变
i 0 1 2 3 4 5 6 7 8 9
mat 1 2 3 -4 5 -8 7 4 2 -10
temp 1 3 6 2 7 -1 7 11 13 3
max 1 3 6 6 7 7 7 11 13 13
最大和为13
思考为什么这样做是对的?
假设一个子数组是我们要找的最大子数组i~j
那么 i<=k<j i~k必定大与0 如果i~k小于0 那么i~j 必定小于 k~j
因此只要前i个和为正就记录并继续往下累加 即可求出最大累加和
public int sumOfSubMatrix(int[][] mat, int n) {
int max = Integer.MIN_VALUE;
int temp;
int[] b = new int[n];
for(int i=0;i<n;i++){
for(int t=0;t<n;t++){//数据使用过后要清空 防止脏数据
b[t] = 0;
}
for(int j=i;j<n;j++){
for(int k=0;k<n;k++){//将二维数组 纵向合并成一维数组
b[k]+=mat[j][k];
}
temp = sumOfSub(b,n);
if(temp>max){
max = temp;
}
}
}
return max;
}
/**一维数组求解子序列最大值问题
* @param mat
* @param n
* @return
*/
public int sumOfSub(int[] mat,int n){
int max = Integer.MIN_VALUE;
int temp = 0;
for(int i=0;i<n;i++){
if(temp<0){
temp = mat[i];
}else{
temp+=mat[i];
}
if(temp>max){
max = temp;
}
}
return max;
}
题目来源:http://www.nowcoder.com/practice/840eee05dccd4ffd8f9433ce8085946b?tpId=8&tqId=11075&rp=5&ru=/ta/cracking-the-coding-interview&qru=/ta/cracking-the-coding-interview/question-ranking